关于std::unique()算法返回非唯一结果的问题咨询
关于std::unique()算法返回非唯一结果的问题咨询
嘿,我太懂你这种困惑了——本来以为用std::unique()就能把容器里的重复元素全清掉,结果跑出来的结果居然还有一堆重复,完全不是预期的“唯一”状态对吧?
其实你踩了一个很多C++新手都会掉的坑:std::unique()的真实作用并不是移除容器里所有的重复元素,它只负责移除相邻的重复元素。它会把容器中连续出现的重复元素移到容器的末尾,然后返回一个迭代器,指向去重后有效元素的最后一个位置。
看你的代码就明白了:你直接生成了1000个0-9的随机数,这些数是完全无序的,重复的元素大多都不相邻(比如可能是3、5、3这种分布)。这种情况下std::unique()只能处理那些刚好挨在一起的重复项,比如连续的两个5会被合并成一个,但不连续的3就会被保留下来,所以最后你看到的908个元素里自然还有大量重复。
要解决这个问题很简单,只需要在调用std::unique()之前,先把容器里的元素排序,让所有相同的元素都变成连续的状态,这样std::unique()就能把所有重复项都移到末尾了。
修改后的代码大概是这样:
#include <algorithm> #include <vector> #include <iostream> int main() { std::vector<int> test; for(int i =0; i < 1000; i++) test.push_back(rand() % 10); // 关键步骤:先排序让重复元素连续 std::sort(test.begin(), test.end()); std::vector<int>::iterator last = std::unique(test.begin(), test.end()); test.erase(last, test.end()); for(int x : test) std::cout << x << "\n"; std::cout << std::distance(test.begin(), last) << "\n"; }
另外提一句,你代码里用erase()删除std::unique()返回的迭代器之后的元素,这步是完全正确的——因为std::unique()本身不会改变容器的大小,只是移动元素,必须配合erase()才能真正把重复元素从容器里删掉。
把排序加上之后,你再跑代码,就能得到0-9这10个完全唯一的元素了,绝对符合你的预期!
内容来源于stack exchange
相关产品推荐
相关产品推荐

