删除标准::列表中的重复项

Remove duplicate items in a std::list

本文关键字:标准 列表 删除      更新时间:2023-10-16

我有一个字符串列表,如何删除 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;
    }