从迭代器中的对象中删除元素的最佳方法是什么?

时间:2012-11-27 04:17:49

标签: arrays algorithm loops

假设您要从迭代内部删除元素:

a = ['a','b','c','d','e'];
for i = 0 to len(a){
    print a[i];
    if (i==1) a.remove(i);
};

输出为a b d e,缺少c。这是一个常见的错误,因为您在数组仍处于循环状态时更改了数组。一些解决方法包括在循环后保留要删除的元素列表,并在删除后更新索引。你是如何处理这个问题的?

3 个答案:

答案 0 :(得分:1)

最明显的方法是从数组的末尾迭代到开头:

a = ['a','b','c','d','e'];
for i = len(a)-1 downto 0 {
    print a[i];
    if (i==1) a.remove(i);
};

许多语言都有迭代器,它支持在前向迭代期间通过告诉迭代器进行删除来删除元素。但是,这并不总是有效(例如,Java Arrays.asList返回的列表的迭代器不支持删除元素,因为列表不“拥有”后备数组。

如果必须使用索引转发迭代,则在删除元素时至少从索引中减去1。这样你就不会跳过元素了。

答案 1 :(得分:0)

这取决于你的迭代器访问 - 包括循环,在你的例子中从0到5迭代,即使位置5可能不再存在 - 是通过集合中的具体位置,或通过抽象引用下一个元素。

例如,Java中的迭代器是抽象类型,因此您可以删除指向的项目,然后可靠地继续迭代其余部分。

在像C这样的语言中,当迭代一个数组时,你通常会遇到你描述的困难,并冒着编写错误代码的风险。也许最好的通用解决方案是累积要删除的“要删除”的一组内容,然后将它们作为单独的步骤处理。只有当您完全了解集合的内部表示以及迭代如何工作时,才能安全地执行删除,然后调整迭代器 - 以及循环的终止条件 - 正确地继续迭代。但是,如果您正在使用数组,那么通常会出现这种情况。这只是一个问题,即额外的调整代码是否比维护“删除”集的代码更简单。

答案 2 :(得分:0)

你甚至可以通过迭代器在迭代中删除它。


vector::iterator itVec = vectInt.begin();
for ( ; itVec != vectInt.end(); )
{
 if (*itVec == 1022) 
  itVec = vectInt.erase(itVect);
 else
  ++itVec;
}

interator响应知道元素的结束(而不是通过记录结束的长度),并释放内存。