删除标准::列表中的重复项
Remove duplicate items in a std::list
我有一个字符串列表,如何删除 std::list 中的重复值,例如
std::list<std::string> listName;
listName.push_back("Foo");
listName.push_back("Bar");
listName.push_back("Foo");
然后我想删除重复的名称"Foo"。剩下的只是"酒吧"的名字。
谢谢!
如果你只想要listName
中的唯一元素,你可以这样做:
listName.sort();
listName.unique();
列表名称应保留:"Foo", "Bar"
如果要摆脱所有重复的元素,可以使用std::list::sort
对元素进行排序,然后使用std::adjacent_find
查找重复的元素。
listName.sort();
std::list<std::string>::iterator ab = std::adjacent_find(listName.begin(), listName.end());
if (ab != listName.end()) // if duplicate elements are found
{
std::list<std::string>::iterator ae = std::upper_bound(listName.begin(), listName.end(), *ab); // try to locate last occurrence
if (std::distance(ab, ae) > 1)
{
listName.erase(ab, ae); // remove all dup elements
}
}
列表名称保留:"Bar"
在这里看到更多std::list
内部界面
执行此操作的一种
方法是使用 std::map
而不是 list
。映射将存储字符串并记录它们出现的次数。对代码的唯一真正更改是需要使用++
而不是push_back
将字符串放入映射中;
std::map<std::string, int> listName;
++listName["Foo"];
++listName["Bar"];
++listName["Foo"];
然后删除计数大于 1 的条目:
for (auto it = listName.begin(); it != listName.end(); )
{
if (it->second > 1)
listName.erase(it++);
else
++it;
}
对列表进行排序,然后您可以轻松找到重复项。
#include <list>
#include <iostream>
#include <algorithm>
int main()
{
std::list<std::string> listName = {"Foo", "Bar", "Foo", "Foobar"};
listName.sort();
for(auto i = listName.begin(); i != listName.end(); )
{
auto range = std::equal_range(i, listName.end(), *i);
if(std::next(range.first) != range.second)
i = listName.erase(range.first, range.second);
else ++i;
}
for(auto const& e : listName) std::cout << e << ", ";
}
我能想到的最短版本,但对要删除的每个元素进行两次迭代(一次在equal_range
,一次在erase
期间)。
或者,对每个元素迭代一次:
listName.sort();
for(auto i = listName.begin(); i != listName.end(); )
{
auto j = std::next(i);
bool duplicate = false;
while(j != listName.end() && *j == *i)
{
duplicate = true;
j = listName.erase(j);
}
if(duplicate) i = listName.erase(i);
i = j;
}
作为练习,将duplicate = true
移出循环:
listName.sort();
for(auto i = listName.begin(); i != listName.end(); )
{
auto j = std::next(i);
bool duplicate = (j != listName.end() && *j == *i);
if(duplicate)
{
do
{
j = listName.erase(j);
}while(j != listName.end() && *j == *i);
listName.erase(i);
}
i = j;
}
相关文章:
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 在子集化后将包含索引号的列表列表映射到标准索引序列
- 移动后是否需要重置标准::列表?
- C++:带有大括号初始化列表的函数调用表达式 - 标准是否规定在单个元素列表的微不足道的情况下忽略大括号?
- C++,标准::列表的左/右旋转
- 标准::列表是循环的吗?
- 标准::p空气<矢量、双精度的初始值设定项列表<int>>
- 在地图和列表之间查找标准容器
- 标准::列表转换和复制
- 从标准列表中删除元素
- 如何在C++中访问标准::列表中的函数
- 擦除标准::列表项时的错误
- 标准::列表::擦除不起作用
- 两个标准::列表之间的距离
- C++ 自己在标准::列表中的比较
- 删除标准::列表中的重复项
- SFML 精灵标准::列表
- 当此列表包含父列表时,如何遍历列表,它使用标准列表
- 标准::列表擦除(可用内存)
- 从标准::列表中删除/擦除