删除字符串向量中的重复项

时间:2012-02-11 02:07:15

标签: c++ vector

我有一个字符串向量:

std::vector<std::string> fName

包含文件名列表<a,b,c,d,a,e,e,d,b>

我想删除所有具有重复项的文件,并且只想保留向量中没有重复项的文件。

for(size_t l = 0; l < fName.size(); l++)
{
    strFile = fName.at(l);
    for(size_t k = 1; k < fName.size(); k++)
    {
        strFile2 = fName.at(k);
        if(strFile.compare(strFile2) == 0)
        {
            fName.erase(fName.begin() + l);
            fName.erase(fName.begin() + k);
        }
    }
}

这是删除了一些副本,但仍然有一些重复,需要帮助调试。

此外,我的输入看起来像<a,b,c,d,e,e,d,c,a>,我的预期输出为<b>,因为所有其他文件b,c,d,e都有重复的文件被移除。

4 个答案:

答案 0 :(得分:14)

#include <algorithm>

template <typename T>
void remove_duplicates(std::vector<T>& vec)
{
  std::sort(vec.begin(), vec.end());
  vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
}

注意:这要求T定义了operator<operator==

为什么会有效?

std::sort使用less-than比较运算符

对元素进行排序

std::unique删除重复的连续元素,使用相等的比较运算符

进行比较

如果我只想要独特的元素怎么办?

然后你最好使用std :: map

#include <algorithm>
#include <map>

template <typename T>
void unique_elements(std::vector<T>& vec)
{   
  std::map<T, int> m;
  for(auto p : vec) ++m[p];
  vec.erase(transform_if(m.begin(), m.end(), vec.begin(),
                         [](std::pair<T,int> const& p) {return p.first;},
                         [](std::pair<T,int> const& p) {return p.second==1;}),
            vec.end());
}

请参阅:here

答案 1 :(得分:3)

如果我理解你的要求,我并不完全确定。你想只保留矢量中不重复的元素,对吗?

将字符串映射为整数,用于计算每个字符串的出现次数。清除向量,然后仅复制仅发生一次的字符串。

map<string,int> m;
for (auto & i : v)
    m[i]++;
v.clear();
for (auto & i : m)
    if(i.second == 1)
        v.push_back(i.first);

或者,对于编译器功能挑战:

map<string,int> m;
for (vector<string>::iterator i=v.begin(); i!=v.end(); ++i)
    m[*i]++;
v.clear();
for (map<string,int>::iterator i=m.begin(); i!=m.end(); ++i)
    if (i->second == 1)
        v.push_back(i->first);

答案 2 :(得分:2)

#include <algorithms>

template <typename T>
remove_duplicates(std::vector<T>& vec)
{
  std::vector<T> tvec;
  uint32_t size = vec.size();
  for (uint32_t i; i < size; i++) {
    if (std::find(vec.begin() + i + 1, vec.end(), vec[i]) == vector.end()) {
      tvec.push_back(t);
    } else {
      vec.push_back(t);
    }
  vec = tvec; // : )
  }
}

答案 3 :(得分:0)

您可以消除O(log n)运行时和O(n)空间中的重复项:

std::set<std::string> const uniques(vec.begin(), vec.end());
vec.assign(uniques.begin(), uniques.end());

但是O(log n)运行时有点误导,因为O(n)空间实际上进行O(n)动态分配,这在速度方面是昂贵的。元素也必须具有可比性(此处为operator<()std::string支持作为词典比较。

如果您只想存储唯一元素:

template<typename In>
In find_unique(In first, In last)
{
    if( first == last ) return last;
    In tail(first++);
    int dupes = 0;
    while( first != last ) {
        if( *tail++ == *first++ ) ++dupes;
        else if( dupes != 0 ) dupes = 0;
        else return --tail;
    }
    return dupes == 0 ? tail : last;
}

上述算法采用有序范围并返回第一个唯一元素,即线性时间和常量空间。要获取容器中的所有唯一标识符,您可以像这样使用它:

auto pivot = vec.begin();
for( auto i(find_unique(vec.begin(), vec.end()));
     i != vec.end();
     i = find_unique(++i, vec.end())) {
    std::iter_swap(pivot++, i);
}
vec.erase(pivot, vec.end());