从容器中获取唯一元素[c++]

Getting unique elements from a container [c++]

本文关键字:元素 c++ 唯一 获取      更新时间:2023-10-16

我希望只从容器中获得唯一的元素。假设srcContainer是我想要唯一元素的容器。我看了三个选项:

  1. 使用std::unique

       std::sort(srcContainer.begin(), srcContainer.end());
       srcContainer.erase(std::unique(srcContainer.begin(), srcContainer.end()), srcContainer.end());
    
  2. 使用BOOST::unique

    boost::erase(srcContainer, boost::unique<boost::return_found_end>(boost::sort(srcContainer)));  
    
  3. 我自己的方法

    std::set<T> uniqueElems(srcContainer.begin(), srcContainer.end());  
    srcContainer.clear();  
    srcContainer.insert(srcContainer.end(), uniqueElems.begin(), uniqueElems.end()); 
    

1的问题。和2。它们改变了成员在原始srcContainer中出现的顺序。与3。顺序没有变化,而且与1相比,它提供了更好的性能。是否因为在3中没有显式排序?上面? ?)。上面3个方法的wall clock时间和srcContainer中元素的数量如下所示:

  1. srcContainer (contains integer) size = 1e+6
    - std::unique = 1.04779 secs
    - BOOST::unique = 1.04774 secs
    - Own method = 0.481638 secs

  2. srcContainer (contains integer) size = 1e+8
    - std::unique = 151.554 secs
    - BOOST::unique = 151.474秒
    - Own method = 57.5693 secs

我的问题是:
    是否有更好的方法来找到唯一使用std::unique或BOOST::unique或任何其他代码和维护容器中的原始顺序?
  1. 使用方法3有问题吗?以上。

对于性能分析,srcContainer创建如下:

std::vector<int> srcContainer;  
int halfWay = numElems/2;  
for (size_t k=0; k<numElems; ++k) {  
   if (k < halfWay)  
      srcContainer.push_back(k);  
   else  
      srcContainer.push_back(k - halfWay);  
}  

编辑:
同意关于方法3的意见。还改变了元素的顺序。有没有更好的方法在不改变顺序的情况下获得唯一元素?

谢谢

根据源数据的信息进行编辑:您看到集合插入完成的速度比向量排序快的原因是,您的输入数据是两个已经排序的范围。对于快速排序(通常由std::sort使用),这是一个退化的情况,也是你可以给它的最糟糕的输入之一。对于1e8的输入大小,将排序从std::sort更改为std::stable_sort,将运行时间从~25s减少到<9s。

如果你想保持原始的项目顺序,你可以尝试像下面这样保持所有项目的散列。我不知道这将是什么性能,但例如,你可以利用哈希和remove_if的方法如下所示:

struct Remover
{
    explicit Remover(hash& found_items) : found_items_(found_items) { }
    bool operator()(const Iter& item) { retval = <does exist in hash>; add to hash; return retval; }
    hash& found_items_;
};
hash dup_finder;
Remover remover(dup_finder);
std::erase(std::remove_if(src.begin(), src.end(), remover), src.end());

我的答案的原始组成部分:

如果源容器中的元素大部分已经排序,使用stable_sort可能会比在调用unique之前排序更好。如果没有关于你的数据集的更多信息,我无法猜测是什么可能导致选项3比1&2.

选项3应该删除唯一项,但请记住,无论您断言什么,它仍然会以与前两个选项完全相同的方式重新排序项。