Pregunta Lista C # - Eliminando elementos mientras se repite / itera [duplicado]


Esta pregunta ya tiene una respuesta aquí:

Supongamos que tengo el siguiente fragmento de código:

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

El siguiente código arroja una excepción.

Mi pregunta es ¿cuál es la mejor manera de evitar esta excepción y eliminar el elemento mientras se repite?


38
2017-09-07 21:33


origen


Respuestas:


Si necesita eliminar elementos, debe iterar hacia atrás para poder eliminar elementos del final de la lista:

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

Sin embargo, hay formas más eficientes de hacerlo con LINQ (como lo indican las otras respuestas).


86
2017-09-07 21:35



Puedes usar List<T>.RemoveAll para manejar esto:

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

39
2017-09-07 21:36



Me encuentro con una solución simple para esto usando foreach y .ToArray()

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

10
2017-07-08 15:00



Puedes probar el método de iteración inversa de ChrisF para eliminar tu artículo.

También puedes simplemente:

List.Remove("One");

O:

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

Y termine con eso. Realmente no tiene sentido iterar sobre la colección para eliminar un solo elemento.


4
2017-09-07 21:37



También puede usar un bucle de movimiento hacia adelante como:

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--);
    }
}

Esta línea data.RemoveAt(i--); está deteniendo el efecto de incremento en la variable de iteración al final del ciclo, en caso de que el elemento se elimine de la lista.

Eliminará el elemento del índice en el valor de iteración actual y luego, después de eliminar el elemento, el iterador se establecerá en un valor menos que el actual. Al final del ciclo, el incremento en el cuerpo del ciclo lo moverá al siguiente índice válido.

Aquí hay un trabajo dotfiddle

(Tenga en cuenta que, personalmente, uso el ciclo inverso para situaciones como estas porque IMO, son más fáciles de entender, esta respuesta aquí es solo para mostrar otra forma de lograrlo).


3
2018-04-15 19:46



¿Por qué no simplemente reduces la variable del iterador?

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

2
2018-06-26 12:07



Aquí hay un truco sucio y me pregunto cuál será su crítica.

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

1
2018-03-21 02:33



La siguiente solución general hace una copia de la lista y maneja el índice negativo:

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

}

1
2017-11-27 14:14



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

0
2017-09-07 21:40