我有一个字符串向量:
std::vector<std::string> fName
包含文件名列表<a,b,c,d,a,e,e,d,b>
。
我想删除所有具有重复项的文件,并且只想保留向量中没有重复项的文件。
for(size_t l = 0; l < fName.size(); l++)
{
strFile = fName.at(l);
for(size_t k = 1; k < fName.size(); k++)
{
strFile2 = fName.at(k);
if(strFile.compare(strFile2) == 0)
{
fName.erase(fName.begin() + l);
fName.erase(fName.begin() + k);
}
}
}
这是删除了一些副本,但仍然有一些重复,需要帮助调试。
此外,我的输入看起来像<a,b,c,d,e,e,d,c,a>
,我的预期输出为<b>
,因为所有其他文件b,c,d,e都有重复的文件被移除。
答案 0 :(得分:14)
#include <algorithm>
template <typename T>
void remove_duplicates(std::vector<T>& vec)
{
std::sort(vec.begin(), vec.end());
vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
}
注意:这要求T定义了operator<
和operator==
。
为什么会有效?
std::sort使用less-than比较运算符
对元素进行排序std::unique删除重复的连续元素,使用相等的比较运算符
进行比较如果我只想要独特的元素怎么办?
然后你最好使用std :: map
#include <algorithm>
#include <map>
template <typename T>
void unique_elements(std::vector<T>& vec)
{
std::map<T, int> m;
for(auto p : vec) ++m[p];
vec.erase(transform_if(m.begin(), m.end(), vec.begin(),
[](std::pair<T,int> const& p) {return p.first;},
[](std::pair<T,int> const& p) {return p.second==1;}),
vec.end());
}
请参阅:here。
答案 1 :(得分:3)
如果我理解你的要求,我并不完全确定。你想只保留矢量中不重复的元素,对吗?
将字符串映射为整数,用于计算每个字符串的出现次数。清除向量,然后仅复制仅发生一次的字符串。
map<string,int> m;
for (auto & i : v)
m[i]++;
v.clear();
for (auto & i : m)
if(i.second == 1)
v.push_back(i.first);
或者,对于编译器功能挑战:
map<string,int> m;
for (vector<string>::iterator i=v.begin(); i!=v.end(); ++i)
m[*i]++;
v.clear();
for (map<string,int>::iterator i=m.begin(); i!=m.end(); ++i)
if (i->second == 1)
v.push_back(i->first);
答案 2 :(得分:2)
#include <algorithms>
template <typename T>
remove_duplicates(std::vector<T>& vec)
{
std::vector<T> tvec;
uint32_t size = vec.size();
for (uint32_t i; i < size; i++) {
if (std::find(vec.begin() + i + 1, vec.end(), vec[i]) == vector.end()) {
tvec.push_back(t);
} else {
vec.push_back(t);
}
vec = tvec; // : )
}
}
答案 3 :(得分:0)
您可以消除O(log n)运行时和O(n)空间中的重复项:
std::set<std::string> const uniques(vec.begin(), vec.end());
vec.assign(uniques.begin(), uniques.end());
但是O(log n)运行时有点误导,因为O(n)空间实际上进行O(n)动态分配,这在速度方面是昂贵的。元素也必须具有可比性(此处为operator<()
,std::string
支持作为词典比较。
如果您只想存储唯一元素:
template<typename In>
In find_unique(In first, In last)
{
if( first == last ) return last;
In tail(first++);
int dupes = 0;
while( first != last ) {
if( *tail++ == *first++ ) ++dupes;
else if( dupes != 0 ) dupes = 0;
else return --tail;
}
return dupes == 0 ? tail : last;
}
上述算法采用有序范围并返回第一个唯一元素,即线性时间和常量空间。要获取容器中的所有唯一标识符,您可以像这样使用它:
auto pivot = vec.begin();
for( auto i(find_unique(vec.begin(), vec.end()));
i != vec.end();
i = find_unique(++i, vec.end())) {
std::iter_swap(pivot++, i);
}
vec.erase(pivot, vec.end());