C ++ std :: unique没有显示我对它的期望

时间:2019-05-30 15:33:59

标签: c++ c++11

我试图查找向量是否包含重复项(请不要提供检查重复项的算法。)我想到了这种奇怪的行为。向量1,2,3,1上的std :: unique应该使其1,2,3,1返回迭代器为1,但擦除迭代器返回到vector.end()时,我得到的向量大小与我是原始向量。这是描述上述行为的代码段(可从ideone获得)

    vector<int> nums2 = {1,2,3,4};  
    vector<int> nums = {1,2,3,1};
    cout << "nums1" << endl;
    vector<int> a(nums.begin(), nums.end());
    auto ip = unique(nums.begin(), nums.begin()+nums.size());
    nums.resize( std::distance(nums.begin(),ip) );
    cout << a.size() <<  " " << nums.size() << endl;

    cout << "Nums2" << endl;
    vector<int> a2(nums2.begin(), nums2.end());
    auto ip2 = unique(nums2.begin(), nums2.begin()+nums2.size());
    nums.resize( std::distance(nums2.begin(),ip2) );
    cout << a2.size() <<  " " << nums2.size();

实际输出是

nums1
4 4
Nums2
4 4

但应该是

nums1
4 3
Nums2
4 4

3 个答案:

答案 0 :(得分:5)

std::unique仅删除连续的重复项。来自std::unique上的cppreference.com:

  

从范围[first,last)中消除每组连续的等效元素中除第一个元素外的所有元素,并为该范围的新逻辑末尾返回一个end-the-end迭代器。 / p>

您的1不是连续的,因此不会被删除。这是预期的行为。快速解决方案是首先std::sort您的范围。

答案 1 :(得分:2)

如果要删除重复的元素,同时又使它们按顺序出现,unique不是您想要的。而是使用unordered_set来跟踪您到目前为止所看到的元素。 (您可以使用remove_if进行此操作,但是除非您熟悉lambda捕获语义,否则我不建议您这样做;只需在for循环中进行操作,然后阅读如何正确地从向量中删除元素在for循环中。)

答案 2 :(得分:1)

您误解了std :: unique的作用;它消除了所有连续元素之外的所有元素。也就是说,它不会删除相邻的重复项。 因此,要删除重复项,您需要确保所有重复项都位于彼此相邻的位置。使用std :: vector执行此操作的最简单方法是先应用std :: sort,然后再应用std :: unique。