我有一个字符串列表,如何删除 std::list 中的重复值,例如
std::list<std::string> listName;
listName.push_back("Foo");
listName.push_back("Bar");
listName.push_back("Foo");
然后我想删除重复的名称“Foo”。剩下的只是“酒吧”的名字。
谢谢!
我有一个字符串列表,如何删除 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();
listName 应保留:"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
}
}
listName 保留:"Bar"
更多界面请参见此处std::list
对列表进行排序,然后您可以轻松找到重复项。
#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;
}
您可以做到这一点的一种方法是使用 astd::map
而不是 a 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;
}