我正在使用foreach
循环迭代QLinkedList
,但如果项目符合特定条件,我需要删除它们。在不打乱循环的情况下,正确的方法是什么?
foreach( Object obj, myLinkedList )
{
if( obj.val == BAD_VAL )
// remove the item from myLinkedList
}
我发现了其他一些问题可以解决这个问题,但不适用于一般情况,如链表。
如果可能的话,我也想知道其他数据结构(如QSet
、QHash
等)。感谢
对于特定情况:
显然,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
}
}
对于一般情况:
如果您使用的是QLinkedList
以外的Qt数据结构,那么很可能有一个迭代器类。如果要修改列表,请使用可变版本。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
我也可以建议一种昂贵但简单的方法来做到这一点。创建另一个列表并将好的对象复制到其中。然后用新列表替换旧列表。
QLinkedList<Object> new_list;
foreach(Object obj, myLinkedList) {
if(obj.val != BAD_VAL) {
new_list << obj;
}
}
list = new_list;
如果您的列表内容很大,请不要这样做。