今天看源码时碰到以下这段代码,收获STL小技巧之利用unique快速删除重复元素;
auto UniLab = mLastFrame.vSemObjLabel;
std::sort(UniLab.begin(), UniLab.end());
UniLab.erase(std::unique( UniLab.begin(), UniLab.end() ), UniLab.end() );
unique函数
unique是一个非常使用的函数,所在的头文件为:
#include <algorithm>
其作用为:去除容器或者数组中相邻且相同的元素。
实际上,unique的做法为当相邻位置出现重复时用下一个元素填补当前的位置,其只修改了[begin, end]之间的数值,并返回一个迭代器result,使得[begin, result]之间没有相邻的相同元素,表现地好像被“删除”了一样。
可以看以下这段代码:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<int> input {0, 1, 3, 3, 2, 2, 3, 5, 5, 6, 7, 7};
int main(){
for(int i: input) cout << i;
cout << endl;
auto output_itr = unique(input.begin(), input.end());
for(int i:input) cout << i;
cout << endl;
cout << "len: " << output_itr-input.begin() << endl;
return 0;
}
其结果为:
013322355677
013235675677
len: 8
从其功能描述和代码的运行结果可以知道unique有几个特点:
①其只对容器的值做修改,不会改变容器的size;
②其返回一个迭代器result,且保证[begin, result]之间没有相邻相同元素;
🌂当我们只选择[begin, result]之间的数据时,就像我们对容器中的相邻元素做了“删除”一样;
两个版本:
其中第一个版本默认使用"=="作为相等判断,第二个版本的第三个参数可以指定比较函数;
template<typename _ForwardIterator>
inline _ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last)
template<typename _ForwardIterator, typename _BinaryPredicate>
inline _ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last,
_BinaryPredicate __binary_pred)
用于删除重复元素
既然unique能够删除相邻的相同元素,那么只要先将容器进行排序,那么就有删除重复元素“==”删除相邻相同元素了;
对上面的代码稍加改动即可完成删除重复元素的目的:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<int> input {0, 4, 3, 7, 5, 2, 3, 2, 5, 6, 3, 7, 4};
int main(){
for(int i: input) cout << i;
cout << endl;
sort(input.begin(), input.end());
auto output_itr = unique(input.begin(), input.end());
for(int i:input) cout << i;
cout << endl;
input.erase(output_itr, input.end());
for(int i: input) cout << i;
cout << endl;
return 0;
}
其结果为:
0437523256374
0234567455677
0234567
总结
sort函数+unique函数可以快速实现去除一个容器中相同元素的目的,在本文中容器存储的是简单的整形数据,当存储数据更复杂时只需:
①将sort函数的compare函数和unique的“==”函数传入即可,和我之前写过的文章类似;
②或者对存储的数据结构的“>”和“= =”做重载;