6

我正在QLinkedList使用foreach循环进行迭代,但是如果它们符合特定条件,我需要删除它们。在不弄乱循环的情况下执行此操作的正确方法是什么?

foreach( Object obj, myLinkedList )
{
    if( obj.val == BAD_VAL )
        // remove the item from myLinkedList
}

我发现了其他可以解决这个问题的问题,但不适用于一般情况,例如链表。

如果可能的话,我还想知道其他数据结构(如QSet,QHash等)。谢谢

4

2 回答 2

19

针对具体情况:

显然foreach循环根本不应该用于修改列表,因为foreach循环实际上是在处理原始列表的副本。如果你修改它,你不仅会因为隐式共享和写时修改而受到惩罚,而且一旦你退出循环,你的更改也会被丢弃。

实现此目的的正确方法是使用迭代器。我更喜欢 Java 风格的迭代器。您会注意到,每种列表类型都有提供简单迭代器的迭代器类。例如QLinkedList,有一个类QMutableLinkedListIterator。它可以按如下方式使用:

Qt 文档中添加了我的评论:

 QMutableLinkedListIterator<int> i(list); // pass list as argument
 while (i.hasNext()) { 
     int val = i.next();                  // retrieve value of current item
     if (val < 0) {
         i.setValue(-val);                // change/set value of current item
     } else if (val == 0) {
         i.remove();                      // delete current item
     }
 }


对于一般情况:

如果您使用的是除 之外的 Qt 数据结构QLinkedList,那么很有可能有一个迭代器类适合您。如果要修改列表,请使用可变版本。这些 API 大致相同。以下是课程:

Structure    |   Immutable Case       |  Mutable Case
-----------------------------------------------------
QList        |   QListIterator        |  QMutableListIterator 
QLinkedList  |   QLinkedListIterator  |  QMutableLinkedListIterator 
QHash        |   QHashIterator        |  QMutableHashIterator
QMap         |   QMapIterator         |  QMutableMapIterator 
QSet         |   QSetIterator         |  QMutableSetIterator 
QStringList  |   QStringListIterator  |  QMutableStringListIterator 
QVector      |   QVectorIterator      |  QMutableVectorIterator
于 2013-07-05T17:29:50.787 回答
0

我还可以建议一种昂贵但简单的方法来做到这一点。创建另一个列表并将好的对象复制到其中。然后用新列表替换旧列表。

QLinkedList<Object> new_list;
foreach(Object obj, myLinkedList) {
  if(obj.val != BAD_VAL) {
    new_list << obj;
  }
}
list = new_list;

如果您的列表内容很大,请不要这样做。

于 2013-07-05T18:49:27.543 回答