Tengo que eliminar algunas filas de una tabla de datos. He oído que no está bien cambiar una colección mientras la repito. Entonces, en lugar de un bucle for en el que verifico si una fila cumple con las demandas de eliminación y luego marcarla como eliminada, primero debo iterar a través de la tabla de datos y agregar todas las filas en una lista, luego recorrer la lista y marcar las filas para las eliminaciones ¿Cuáles son las razones para esto y qué alternativas tengo (en lugar de utilizar la lista de filas quiero decir)?Cómo modificar o eliminar elementos de una colección enumerable mientras se itera en C#
Respuesta
Puede eliminar elementos de una colección si utiliza un simple bucle for
.
Tome un vistazo a este ejemplo:
var l = new List<int>();
l.Add(0);
l.Add(1);
l.Add(2);
l.Add(3);
l.Add(4);
l.Add(5);
l.Add(6);
for (int i = 0; i < l.Count; i++)
{
if (l[i] % 2 == 0)
{
l.RemoveAt(i);
i--;
}
}
foreach (var i in l)
{
Console.WriteLine(i);
}
Esto está defectuoso ya que no todos los elementos serán revisados. Si elimina un elemento en i, entonces el elemento en i + 1 se convierte en i. Cuando i se incremente para el siguiente ciclo, omitirá el elemento que acaba de reemplazar el elemento eliminado (espero que tenga sentido). –
Corregí esto. Gracias Andy por la bofetada. Pero mi punto fue que puedes cambiar una colección con un ciclo for. –
¿Puedo utilizar l [i] .Delete(), ya que eliminar creará problemas con el adaptador de tabla en el procedimiento de actualización (las filas se eliminarán de la tabla en lugar de simplemente marcarse como eliminadas). – kjv
Un bucle while manejaría esto:
int i = 0;
while(i < list.Count)
{
if(<codition for removing element met>)
{
list.RemoveAt(i);
}
else
{
i++;
}
}
Esta solución enfrenta el mismo problema que el anterior, sus índices estarán desactivados si elimina un elemento. – Element
No lo harán, ya que el índice solo se incrementa cuando el elemento no se elimina. –
suprimir o añadir a la lista, mientras que la iteración a través de él se puede romper, como usted ha dicho.
menudo he utilizado un enfoque de dos lista para resolver el problema:
ArrayList matches = new ArrayList(); //second list
for MyObject obj in my_list
{
if (obj.property == value_i_care_about)
matches.addLast(obj);
}
//now modify
for MyObject m in matches
{
my_list.remove(m); //use second list to delete from first list
}
//finished.
Este enfoque es realmente bueno y también seguro para subprocesos. –
¿Quizás podrías editarlo para que sea el código C#? –
Puesto que usted está trabajando con un DataTable y la necesidad de ser capaces de persistir los cambios de vuelta al servidor con un adaptador de la tabla (véase los comentarios), aquí es un ejemplo de cómo se debe eliminar filas:
DataTable dt;
// remove all rows where the last name starts with "B"
foreach (DataRow row in dt.Rows)
{
if (row["LASTNAME"].ToString().StartsWith("B"))
{
// mark the row for deletion:
row.Delete();
}
}
Calling borrar en las filas cambiará su propiedad RowState como eliminado, pero deje las filas eliminadas en la tabla. Si aún necesita trabajar con esta tabla antes de continuar con los cambios en el servidor (por ejemplo, si desea mostrar el contenido de la tabla menos las filas eliminadas), debe verificar el RowState de cada fila mientras lo itera de esta manera. :
foreach (DataRow row in dt.Rows)
{
if (row.RowState != DataRowState.Deleted)
{
// this row has not been deleted - go ahead and show it
}
}
filas Eliminación de la colección (como en la respuesta de Bruno) se romperá el adaptador de la tabla, y en general no debe hacerse con un DataTable.
Iterar al revés a través de la lista suena como un mejor enfoque, porque si quita un elemento y otros elementos "caen en la brecha", eso no importa porque ya los ha examinado. Además, no tiene que preocuparse de que su variable contraria se vuelva más grande que .Count.
List<int> test = new List<int>();
test.Add(1);
test.Add(2);
test.Add(3);
test.Add(4);
test.Add(5);
test.Add(6);
test.Add(7);
test.Add(8);
for (int i = test.Count-1; i > -1; i--)
{
if(someCondition){
test.RemoveAt(i);
}
}
Cuando necesito eliminar un elemento de una colección que estoy enumerando lo general enumerar a la inversa.
Tomando el código de @bruno, lo haría al revés.
Porque cuando retrocede, los índices de matriz faltantes no interfieren con el orden de su ciclo.
var l = new List<int>(new int[] { 0, 1, 2, 3, 4, 5, 6 });
for (int i = l.Count - 1; i >= 0; i--)
if (l[i] % 2 == 0)
l.RemoveAt(i);
foreach (var i in l)
{
Console.WriteLine(i);
}
Pero seriuosly, en estos días, que haría uso de LINQ: solución
var l = new List<int>(new int[] { 0, 1, 2, 3, 4, 5, 6 });
l.RemoveAll(n => n % 2 == 0);
+1 para darse cuenta del poder de LINQ para algo como esto. ¿Por qué hacer las cosas a lo largo cuando no tienes que – BenAlabaster
por qué no definir la lista l como List
+ 1 para RemoveAll. Nota RemoveAll no es estrictamente LINQ. Está disponible para cualquier clase 'List' en .NET 2.0 sin soporte de LINQ. –
de chakrit también se puede utilizar si se apuntan a .NET 2.0 (sin expresiones LINQ/lambda) utilizando un delegado en lugar de una expresión lambda:
public bool IsMatch(int item) {
return (item % 3 == 1); // put whatever condition you want here
}
public void RemoveMatching() {
List<int> x = new List<int>();
x.RemoveAll(new Predicate<int>(IsMatch));
}
- 1. Eliminar elementos de una colección en java mientras se itera sobre él
- 2. Java: cómo eliminar elementos de una lista mientras se itera/se agrega
- 3. Eliminar elementos de una lista mientras se itera sin usar memoria extra en Python
- 4. ¿Cómo eliminar una clave de HashMap mientras se itera sobre ella?
- 5. Borrar/Eliminar el contenido del mapa (o cualquier otro contenedor STL) mientras lo itera
- 6. ¿Cómo agregar elementos en la Lista mientras se itera en Java?
- 7. Colección modificar elemento
- 8. Cómo adjuntar una colección enumerable a una lista existente en C#
- 9. ¿Cómo eliminar elementos seleccionados de ListBox cuando se le asigna una fuente de datos en C#?
- 10. ¿Cómo puedo modificar una colección de cola en un bucle?
- 11. Agregar a una matriz mientras itera
- 12. ¿Cómo puedo eliminar elementos de una QList mientras la repito utilizando foreach?
- 13. El mejor método para cambiar una lista mientras se itera sobre ella
- 14. Hibernar: la mejor manera de eliminar elementos en una colección
- 15. La mejor manera de eliminar elementos de una colección
- 16. Buscar y eliminar elementos de la colección
- 17. Itera y devuelve un conjunto de n elementos consecutivos
- 18. Modificar .NET Dictionary mientras se lo enumera
- 19. Mongoose.js: eliminar colección o DB
- 20. Cómo extraer elementos de una colección en Java?
- 21. Obtener próximos N elementos de enumerable
- 22. "La colección de elementos no se puede modificar cuando se establece la propiedad DataSource".
- 23. HashSet Iterando al eliminar elementos en C#
- 24. ¿cómo se itera a través de una matriz en fortran?
- 25. Excepción durante la iteración en la colección y eliminar elementos de esa colección
- 26. Suma de elementos en una colección
- 27. ¿Cómo multiplico todos los elementos en una colección con todos los elementos en otra colección?
- 28. Algoritmos para atravesar una colección en orden ordenado sin modificar la colección?
- 29. Ordenar una gran colección mientras se muestra el progreso
- 30. C# Enumerable Rango
He editado el título para que sea más fácil encontrar esta pregunta. Hubo un engañador que cerré antes, pero puedo ver cómo el usuario podría haber perdido esta pregunta con el título anterior. –