Подтвердить что ты не робот

Список С# - Удаление элементов во время цикла/итерации

Предположим, что у меня есть следующий фрагмент кода:

var data=new List<string>(){"One","Two","Three"};
for(int i=0 ; i<data.Count ; i++){
  if(data[i]=="One"){
    data.RemoveAt(i);
  }
}

Следующий код генерирует исключение.

Мой вопрос - это лучший способ избежать этого исключения и удалить элемент во время цикла?

4b9b3361

Ответ 1

Если вам нужно удалить элементы, вы должны выполнить итерацию назад, чтобы вы могли удалить элементы из конца списка:

var data=new List<string>(){"One","Two","Three"};
for(int i=data.Count - 1; i > -1; i--)
{
    if(data[i]=="One")
    {
        data.RemoveAt(i);
    }
}

Однако есть более эффективные способы сделать это с помощью LINQ (как указано в других ответах).

Ответ 2

Вы можете использовать List<T>.RemoveAll, чтобы справиться с этим:

data.RemoveAll(elem => elem == "One");

Ответ 3

Я встречаюсь с простым решением для этого, используя foreach и .ToArray()

  var data=new List<string>(){"One","Two","Three"};
   foreach ( var d in data.ToArray()){
      if(d =="One"){
        data.Remove(d);
      }
    }

Ответ 4

Вы можете попробовать метод обратной итерации ChrisF для удаления вашего элемента.

Вы также можете просто:

List.Remove("One");

Или:

List.RemoveAll(i => i == "One"); // removes all instances

И сделай это. Там действительно нет смысла перебирать коллекцию, чтобы удалить один элемент.

Ответ 5

Вы также можете использовать прямой движущийся контур, например:

var data = new List<string>() { "One", "Two", "Three", "One", "One", "Four" };
for (int i = 0; i < data.Count; i++)
{
    if (data[i] == "One")
    {
        data.RemoveAt(i--);
    }
}

Эта строка data.RemoveAt(i--); останавливает эффект приращения переменной итерации в конце цикла, в случае удаления элемента из списка.

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

Вот рабочий dotfiddle

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

Ответ 6

Почему бы вам просто не просто уменьшить переменную итератора?

var data=new List<string>(){"One","Two","Three"};
for(int i=0 ; i<data.Count ; i++){
  if(data[i]=="One"){
    data.RemoveAt(i);
    i--; // <<<<<<<<<<<
  }
}

Ответ 7

Вот грязный трюк, и мне интересно, какой будет его критика?

var data=new List<string>(){"One","Two","Three"};
foreach (string itm in (data.ToArray()))
{
  if string.Compare(name, "one", true) == 0) data.Remove(name);
}

Ответ 8

Следующее общее решение делает копию списка и обрабатывает отрицательный индекс:

foreach (void item_loopVariable in MyList.ToList) {
    item = item_loopVariable;

}

Ответ 9

        var data = new List<string>() { "One", "Two", "Three" };
        data.RemoveAll(p=>p=="One");

Ответ 10

var data=new List<string>(){"One","Two","Three"};
for(int i=0; i<data.Count; ){
  if(data[i]=="One") data.RemoveAt(i);
  else ++i;
}

Ответ 11

Вы можете использовать класс Stack

        Stack<string> myStack = new Stack<string>();

        foreach (var item in Enumerable.Range(1,1001))
            myStack.Push("Str " + item.ToString());

        while (myStack.Any())
            Console.WriteLine("Now {0} items in Stack, removed item is {1}",myStack.Count,myStack.Pop());

        Console.ReadKey();

Ответ 12

Мне пришлось удалить более одного элемента из списка. поэтому я повторно инициализировал подсчет списка. Есть ли другой лучший вариант?

for (int i = dtList.Count - 1; dtList.Count > 0; )
{
     DateTime tempDate = dtList[i].Item1.Date;
     var selectDates = dtList.FindAll(x => x.Item1.Date == tempDate.Date);
     selectDates.Sort((a, b) => a.Item1.CompareTo(b.Item1));
     dtFilteredList.Add(Tuple.Create(selectDates[0].Item1, selectDates[0].Item2));
     dtList.RemoveAll(x => x.Item1.Date == tempDate.Date);
     i = dtList.Count - 1;
}

Ответ 13

List<string> list = new List<string>();
     list.Add("sasa");
     list.Add("sames");
     list.Add("samu");
     list.Add("james");
     for (int i = list.Count - 1; i >= 0; i--)
     {

         list.RemoveAt(i);

    }