2009-10-07 295 views
23

,以便消除XElements,我有一个bug,除去在foreach循环

foreach (XElement x in items.Elements("x")) 
{ 
    XElement result = webservice.method(x); 

    if (/*condition based on values in result*/) 
    { 
     x.Remove(); 
    } 
} 

的问题是,调用x.Remove()改变的foreach这样,如果有两个元素(“X”),并且第一个被删除,循环不会到达第二个x元素。

那么我该如何循环呢?还是应该以另一种方式重写?

+8

其实我刚才修改的foreach是“的foreach(在items.Elements的XElement X(” X“)。反向())”,并且似乎正常工作的问题之前是在foreach移动索引向上,并且“删除”将所有内容都向下移动,导致项目被跳过。颠倒秩序似乎是有道理的。但是,如果有人有更好的解决方案,我会将问题解决。 – CaffGeek 2009-10-07 17:00:48

+0

我做了一个循环,我不得不做一个我 - 如果它实际上删除了一个项目来弥补索引。尽管如此,你的方式似乎并不是一个坏的选择,但我不是一个.NET专家,所以我有点怀疑我说的是什么,哈哈。 – Xaisoft 2009-10-07 17:09:28

+0

转换为C#3.0。有没有C#版本3.5(详细信息请参阅此文章http://stackoverflow.com/questions/247621/what-are-the-correct-version-numbers-for-c) – Vaccano 2009-10-16 19:46:25

回答

30

我怀疑Linq可能能够帮助你在这里如下。

using System.Linq; 

void foo() 
{ 
    items.Elements("x") 
     .Where(x => condition(webservice.method(x))) 
     .Remove(); 
} 

如果不工作(即,内部枚举仍然无效),使所选择的元素的浅拷贝和删除它们如下。

using System.Linq; 

void foo() 
{ 
    List xElements = items.Elements("x") 
          .Where(x => condition(webservice.method(x))) 
          .ToList(); 

    for (int i = xElements.Count - 1; i > -1; i--) 
    { 
     xElements[i].Remove(); 
    } 
} 
+0

+1如果您使用的是.Net 3.5的理想情况 – 2009-10-09 18:08:45

+0

第一个代码片段适用于我。好的解决方案+1 – 2010-04-21 09:55:55

+0

请注意,每个Remove()都会从第一个孩子开始遍历子元素的内部链接列表,因此每个删除的计算复杂度为O(N)。是否有O(1)方法去除元素? – redcalx 2014-11-26 11:39:55

1

在循环逻辑之前创建一个集合,将要删除的元素添加到新集合中,然后在新集合中的每个元素上调用items.Remove。

+0

这应该工作。我记得这样做。我的答案可能不好。我记得如果你对列表或其他东西进行了修改,那么使用for是一个好主意,但是如果你只是循环而不做任何修改,那么foreach就没有问题。它是否正确? – Xaisoft 2009-10-07 16:55:13

1

尝试没有而不是foreach。