Как перебрать список, который изменяется?

2

У меня есть список строк из набора данных, который мне нужно пропустить.

Проблема в том, что обработка в итерации может удалить одну или несколько строк из списка.

Поскольку список изменяется, я не могу использовать цикл foreach().

Но так как возможно, некоторые из делеций могут возникать в элементах, предшествующих той, которую я обрабатываю, я также не могу использовать цикл for() (т.е. если я обрабатываю элемент, и это приводит к удаление элемента и других элементов, я не могу придумать способ настроить i, чтобы правильно указать на элемент, следующий за тем, который я обрабатывал).

Как бы вы справились с этой проблемой? Мое настоящее подумало, что всегда обрабатывать первый элемент в списке. Если он удаляется, обработайте новый первый элемент. Если он не удаляется, переместите его в список "уже обработанный" и обработайте новый первый элемент.

Есть ли более простой способ?

Теги:
list
iteration

5 ответов

2
Лучший ответ

При изменении списка, который я выполняю, я всегда считаю, что проще всего создать новый список с элементами, которые я хочу сохранить, а затем использовать новый список для выполнения того, что я собирался делать.

По-моему, действительно зависит от того, что вы делаете с данными, когда закончите.

  • 0
    Это то направление, к которому я склоняюсь. Спасибо за подтверждение.
8

Обычно это делается с помощью обратной петли:

List<string> Items = ...
for(int i = Items.Count - 1; i >= 0; i--)
{
   if(Items[i] == "DELETE ME")
   {
      Items.RemoveAt(i);
   }
}

Это приводит к обработке элементов в обратном порядке, поэтому, если вы удаляете элемент, это не влияет на позицию любых элементов, которые еще предстоит обработать.

  • 0
    Это не будет работать в случае, который я рассматриваю, потому что удаления могут происходить не только в элементе i, но и в других элементах i +/- n, что означает, что i-- может указывать или не указывать на правильный следующий элемент. Кроме того, удаление более одного элемента может потенциально оставить i или даже i--, указывая на более не существующий объект за концом списка. (Обратите внимание, что я не обязательно знаю, сколько элементов могло быть удалено.)
0
for(int i = list.Length -1, i >= 0; i--)
{
   // process and delete if you want
}
  • 0
    Пожалуйста, объявите i
  • 0
    Смотрите мой комментарий к Дэвиду выше.
0


int i = 0;
while (i < dataSet.Tables[0].Rows.Count) {
    if (some_condition) {
       dataSet.Tables[0].Rows.RemoveAt(i);
       continue;
    }
    i++;
}
  • 0
    Если происходит более чем одно удаление (условие, которое я не могу легко узнать), то i (или i ++) не будет указывать на правильный следующий элемент. (Причиной может быть более одного удаления из-за каскадного удаления в отношении «один ко многим».)
  • 0
    Да, если вы удаляете (а не удаляете) строку. Но мой пример удаляет строки из DataTable. Если вы используете Delete (), вы можете проверить RowState == RowState.Deleted каждой строки в вашем цикле.
0

Если вы можете получить свои данные в связанном списке, вы будете золотыми.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню