2009-10-07 4 views
23

Итак, у меня есть ошибка, чтобы удалитьУдаление XElements в цикле Еогеасп

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

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

Проблема заключается в том, что вызов x.Remove() изменяет Еогеасп таким образом, что если есть два элемента («х»), и первый удаляется, цикл не попадает во второй элемент x.

Итак, как я должен зацикливать это? Или это должно быть переписано другим способом?

+8

Я на самом деле просто модифицировали Еогеасп быть «Еогеасп (XElement х в items.Elements (» х «). Reverse())» и это, кажется, работает хорошо, как проблема, прежде чем была Еогеасп перемещена индекс вверх, а «Удалить» сдвинул все вниз, в результате чего элементы были пропущены. Кажется, что изменение порядка выглядит. Но я оставлю вопрос открытым, если у кого-то есть лучшее решение. – CaffGeek

+0

Я сделал цикл for, где мне пришлось сделать i - если бы он фактически удалил элемент, чтобы компенсировать индекс. Твой путь с обратным не похож на плохой вариант, хотя, но я не эксперт .NET, поэтому я немного скептически отношусь к тому, что я говорю, lol. – Xaisoft

+0

сохранен в C# 3.0. Нет C# с версией 3.5 (см. Это сообщение для деталей http://stackoverflow.com/questions/247621/what-are-the-correct-version-numbers-for-c) – Vaccano

ответ

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 –

+0

Первый фрагмент кода работал для меня. Отличное решение. +1 –

+0

Обратите внимание, что каждый Remove() перемещает внутренний связанный список дочерних элементов с первого дочернего элемента вперед, поэтому вычислительная сложность каждого удаления равна O (N). Существует ли O (1) способ удаления элементов? – redcalx

1

Создайте коллекцию перед логикой цикла, добавьте элементы, которые нужно удалить в новую коллекцию, а затем вызовите items.Remove на каждый элемент новой коллекции.

+0

Это должно сработать. Я помню, как это делалось. Мой ответ, вероятно, не очень хорош. Я что-то помню, если вы вносите изменения в список или что-то в этом роде, это хорошая идея для использования, но если вы просто зацикливаетесь без каких-либо изменений, foreach в порядке. Это верно? – Xaisoft