2012-02-11 81 views
9

我有一个字符串矢量:在字符串中的向量中删除重复

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有他们删除重复项。

+0

你想保留任何副本的副本吗?即你想,还是只有? – 2012-02-11 02:11:25

+0

我不想保留dupilcates的副本。 – 2012-02-11 02:14:28

回答

11
#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排序利用其小于比较操作

std::unique删除重复的连续元素,用他们平等的比较操作

比较它们的元素如果我只想要独特的元素?

那你最好使用std ::地图

#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

+0

还需要包括#include 为std :: sort和std :: unique才能工作。 – 2012-02-11 02:19:09

+0

Gigi谢谢你这个工作,但并没有解决我原来的问题...我开始与我想我的输出是而不是 2012-02-11 02:20:08

+0

对不起,我想我的输出是这是不重复。 – 2012-02-11 02:26:43

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
#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; // :) 
    } 
} 
+0

显然这不是有效的 – perreal 2012-02-11 02:40:45

+1

'std :: vector'没有'pop_front()' – 2012-02-11 02:46:37

+0

只有pop_back()找不到pop_front()。林德利先生会很棒,如果你可以帮忙的话。谢谢你,perreal – 2012-02-11 02:49:26

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()); 
+0

坦白说,我会用'std :: sort()'和'std :: unique()'方法。我只是想我会展示一个替代方案。:) – wilhelmtell 2012-02-11 02:48:04

+0

在任何情况下(性能等)都有一个可怕的例子,对于那些懒得无法检查算法的人来说,图书馆 – newhouse 2017-11-24 09:44:05

0

尽管已经回答了。

排序和唯一