C++ 列表删除重复字符串

C++ list remove duplicates strings

提问人:Lumpi 提问时间:1/20/2011 最后编辑:casablancaLumpi 更新时间:1/21/2011 访问量:1921

问:

我在使用列表时遇到了一些问题。

我所拥有的:我正在阅读聊天框中的行,其中不时出现新的文本行。 我总是从盒子里取出最后 20 行,然后我想将它们与我之前取到的所有行进行比较。如果发现一条新生产线,它将被发送到外部功能,该外部功能将拆卸该生产线以进行进一步处理。在我使用数组和向量之前,但列表似乎是更好的方法。

我的想法:我有一个名为 usedlines 的列表,其中包含所有旧的 allready used 行。 列表 fetchedLines 包含从聊天框中获取的最新 20 行。

不,我只是想循环通过它们两个,以确定获取的行是否包含以前从未见过的新行。循环结束后,fetchedlines 中的剩余部分将处理到下一个函数。

问题:当我循环这个循环时,我过了一会儿会得到一个坏指针。为什么? 奖励:有没有人有更好的主意来解决这个任务?

typedef list<string> LISTSTR;
LISTSTR::iterator f;
LISTSTR::iterator u;
LISTSTR fetchedlines;                 
LISTSTR usedLines;                



fetchedlines.insert(fetchedlines.end(), "one");
fetchedlines.push_back("two");
fetchedlines.push_back("three");
fetchedlines.push_back("four");
fetchedlines.push_back("three");

usedLines.push_back("three");
usedLines.push_back("blää");
usedLines.push_back("lumpi");
usedLines.push_back("four");


 for (u =  usedLines.begin(); u != usedLines.end(); u++)
 {
 for (f =  fetchedlines.begin(); f != fetchedlines.end(); f++)
   {
   if(*u==*f)
    fetchedlines.remove(*f);
  }

}
C++ 列表 唯一

评论

2赞 Fred Foo 1/20/2011
查看 ,以获得更快的解决方案。std::setstd::remove_ifstd::set_intersection

答:

5赞 James 1/20/2011 #1

调用 使迭代器失效。fetchedlines.remove(*f)

编辑:

您遇到的问题的可能解决方案是迭代并删除其中包含的所有元素。usedLinesfetchedlines

for (u = usedLines.begin() u != usedLines.end(); u++)
    fetchedLines.remove(*u);

//Process all of fetchedLines

评论

0赞 Lumpi 1/20/2011
该死的,这听起来很聪明!谢谢你的想法,我会试一试;-)
0赞 James 1/20/2011
有比这更快的解决方案,例如拉斯曼建议,但这至少应该可以解决问题。
0赞 Lumpi 1/21/2011
好的,它是这样工作的!!我仍然有点被困在阵列中思考,所以我会看看 larsmans 的建议。感谢大家朝着正确的方向努力。
2赞 Xavier V. 1/20/2011 #2

您正在从中删除一个元素,而您正在迭代它。fetchedlines

这就是为什么你得到一个糟糕的指针。

评论

0赞 Lumpi 1/20/2011
听起来合乎逻辑......所以我必须先遍历整个事情,并记住我以后要删除哪些元素(在循环遍历整个事情之后)?!
0赞 Xavier V. 1/20/2011
这不是一种性感的方式。看看戈兹还是詹姆斯的答案......这些更性感。
0赞 Goz 1/20/2011 #3

因为 *f 是一个迭代器,指向您刚刚擦除的元素。

请尝试以下操作:

if(*u==*f)
{
    LISTSTR::iterator t = f;;

    f--;
    fetchedlines.remove(*t);
}

顺便说一句,删除在列表中搜索与迭代器 f 指向的数据匹配的内容。如果你想简单地摆脱指向你的数据,你最好这样做

f = fetchedlines.erase( f );
f--;
3赞 vmpstr 1/20/2011 #4

出现错误的原因是 fetchedlines.remove (*f) 修改了 fetchedlines,如果它是最后一个元素,则 for 循环增量太大

试试这样的方法:

for (u = userLines.begin (); u != usedLines.end (); ++u)
{
    for (f = fetchedlines.begin (); f != fetchedlines.end ();)
    {
        if (*u == *f)
        {
            f = fetchedlines.erase (f);
        }
        else
        {
            ++f;
        }
    }
}

(当然,这并没有解决这是否是解决问题的好方法)

2赞 Thomas 1/20/2011 #5

在循环访问列表(或几乎任何其他容器)时,绝不能修改它。这是你眼前的问题。

一个更有趣的问题是,你为什么一开始就这样做。有没有办法获得行上的序列号,或者时间戳,所以你可以比较它们?

评论

0赞 Lumpi 1/20/2011
我想到了这样的事情,但是我读到的行中没有行号或时间戳......我想过改变列表的 .unique 功能,如果它发现重复项,它不仅会删除“很多”元素,还会删除邪恶的双胞胎......
0赞 Lumpi 1/21/2011
“在迭代列表(或几乎任何其他容器)时,绝不能修改它。”我会把这个建议放在我的小蓝皮书中,并附上关于 c++ 的注释。谢谢
0赞 Blastfurnace 1/21/2011 #6

这可以通过 和 lambda 表达式来完成。此方法仍然是两个嵌套循环,但它们隐藏在函数调用中。对于小型列表来说,这可能足够快,但不能很好地扩展。如果对数据进行排序或使用订购的容器,则速度可能会快得多。list::remove_if

fetchedLines.remove_if([&](std::string &str)
{
    return std::find(usedLines.begin(), usedLines.end(), str) != usedLines.end();
});