在保持顺序的同时从std :: vector中删除/删除重复元素的方法?

时间:2013-08-03 14:11:54

标签: c++ vector stl

是否有办法在保持顺序的同时从包含字符串元素的向量容器中删除重复元素。

直到现在我使用了set方法,但它没有保留顺序。

我不知道如何使用remove_if来解决这个问题。

5 个答案:

答案 0 :(得分:6)

如何使用临时容器:

std::vector< int >::iterator i , j ;
std::set< int > t_set;
for( i = v.begin() , j = v.begin() ; i != v.end() ; ++i )
    if( t_set.insert( *i ).second) 
        *j++ = *i ;
v.erase( j , v.end() ); 

使用std::remove_if,我可以想到这个:

std::set<int> t_set;
std::vector<int> res; //Resultant vector

remove_copy_if(v.begin(), v.end(), std::back_inserter(res), 
    [&t_set](int x){ 
        return !t_set.insert(x).second; 
    } );

答案 1 :(得分:2)

您可以创建一个空数组,然后迭代原始矢量,只复制矢量中每个项目的第一个实例。您可以通过将其添加到集合中并在将其添加到新阵列之前检查集合中的项目存在来跟踪您是否已在向量中看到项目。

答案 2 :(得分:1)

你可以这样做:

 std::vector<int> v = { 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 8 };
 // 1 2 2 3 4 5 6 7 8 9 8

 for(size_t i=0;i<v.size();i++)
 {
     for(size_t j=0;j<v.size();j++)
     {
         if(v[i] == v[j] && i != j)
         {
              v.erase(v.begin()+j);
              j--; // Fix for certain datasets ie: 
         }         //                             1 2 1 1
     }   
 }

 // Produces:
 // 1 2 3 4 5 6 7 8 9

答案 3 :(得分:1)

一个简单的解决方案

std::vector<int>::iterator it;
it = std::unique (myvector.begin(), myvector.end());

此迭代器将指向最后一个元素旁边的元素。如果不需要,您可能不会使用此迭代器。

有关详细信息,请参阅THIS

编辑:

由于我认为向量将被排序,新的解决方案可能是:

    vector<int> vec= {5,1,2,3,5,4,2,1,1,4,3,2,4,5,2,1,3,5,2,3,5,2,3,2,3,5,2,1,3};
    set<int> s; 
    vector<int>::iterator vecIter=vec.begin();
    vector<int>::iterator vecIterCopy;
    for(;vecIter!=vec.end(); vecIter++) 
    {
        if(s.find(*vecIter)==s.end()) 
        {
            s.insert(*vecIter);
            *vecIterCopy++ = *vecIter;
        }
    }

答案 4 :(得分:1)

O(n * log(n))解决方案:

vector<string> V={"aa","bb","aa","cc","cc"};
set<string> S; 

auto i=V.begin();
auto j=i;

for(; i!=V.end(); ++i) {
    if(S.insert(*i).second  &&  i!=j++) 
        *j = std::move(*i);
}

V.erase(j,V.end());

还使用std::remove_copy_if修改了POW的版本。但这里没有多余的临时性:

set<string> S;
V.erase(
    copy_if(
        make_move_iterator(V.begin()),
        make_move_iterator(V.end()),
        V.begin(),
        [&](const string& x){ return S.insert(x).second;}
    ),
    V.end()
);