有效删除C ++ STL向量中的双重条目?

时间:2012-11-09 09:06:28

标签: c++ algorithm boost stl

  

可能重复:
  C++ Delete Duplicate Entries in a vector

我需要删除C ++ STL向量中的双重条目。重要的一点是,结果向量中元素的顺序必须等于输入向量中的顺序。是否有算法(例如在stl,boost中)可以做到这一点?

4 个答案:

答案 0 :(得分:4)

这里有两种可能的情况:矢量已经排序或者不是。

如果是,std::erasestd::unique可以轻松解决此问题,如其他答案中所示。

如果不是那么你可以用

来实现目标
v.erase(std::remove_if(v.begin(), v.end(), predicate), v.end());

但是有一个问题是predicate并不容易指定:它是一个接受一个参数(要考虑的值)的函数,它需要回答问题“向量中是否有任何相等的值?”。由于你没有被告知提供的参数在向量中的确切位置,这意味着你必须保持相当多的手动状态才能回答这个问题。

这里一个方便的选择是使用std::set来完成一些繁重的工作:

std::set<decltype(v)::value_type> set(v.begin(), v.end());
v.erase(
    std::remove_if(
        v.begin(), 
        v.end(), 
        [&set] (decltype(v)::value_type item) { return !set.erase(item); }), 
    v.end());

这样做是使用向量中的值预先填充std::set,然后通过查看是否已从集合中删除项目来检查项目之前是否已被查看过。这样,结果将只保留输入中比较相等的每组项目中的第一项。

See it in action

答案 1 :(得分:3)

如果你的矢量没有排序,你不能只使用std::unique(同样不能对它进行排序会破坏你的订单),你可以使用类似这个函数的东西(使用C ++ 11 lambdas): / p>

template<typename FwdIt> FwdIt unordered_unique(FwdIt first, FwdIt last)
{
    typedef typename std::iterator_traits<FwdIt>::value_type value_type;
    std::set<value_type> unique;
    return std::remove_if(first, last, [&unique](const value_type &arg) { 
                                           return !unique.insert(arg).second; });
}

可以使用通常的erase-romve-idiom调用:

v.erase(unordered_unique(v.begin(), v.end()), v.end());

当然,你也可以使用C ++ 11的std::unordered_set代替std::set(当然,对于可混合类型),以便在平均情况下远离O(n log n)。

答案 2 :(得分:2)

std::unique怎么样?

auto firstDup = std::unique(myvector.begin(), myvector.end());

答案 3 :(得分:0)

使用下一个:
vec.erase( unique( vec.begin(), vec.end() ), vec.end() );