2009-10-07 10 views
23

Por lo tanto, tienen un error de eliminarXElements retirar en un bucle foreach

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

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

El problema es que llamar x.Remove() altera el foreach de tal manera que si hay dos elementos ("x"), y el primero se elimina, el ciclo no llega al segundo elemento x.

Entonces, ¿cómo debería estar bucleando esto? ¿O debería ser reescrito de otra manera?

+8

De hecho, me acaban de modificación del foreach para ser "foreach (x XElement en items.Elements (" x "). Reverse())", y que parece funcionar muy bien como el problema antes era el foreach trasladó la index up, y Remove eliminó todo, causando saltos de elementos. Invertir el orden parece tener sentido. Pero dejaré la pregunta abierta en caso de que alguien tenga una mejor solución. – CaffGeek

+0

Hice un bucle for donde tuve que hacer un i-- si realmente eliminó un elemento para compensar el índice. Tu camino con el reverso tampoco parece una mala opción, pero no soy un experto en .NET, así que soy un poco escéptico de lo que digo, jaja. – Xaisoft

+0

retenido a C# 3.0. No hay C# con la versión 3.5 (consulte esta publicación para obtener detalles http://stackoverflow.com/questions/247621/what-are-the-correct-version-numbers-for-c) – Vaccano

Respuesta

30

Sospecho que Linq puede ayudarlo aquí de la siguiente manera.

using System.Linq; 

void foo() 
{ 
    items.Elements("x") 
     .Where(x => condition(webservice.method(x))) 
     .Remove(); 
} 

Si eso no funciona (es decir, el empadronador interno aún está invalidado), hacer una copia superficial de los elementos seleccionados y eliminarlos de la siguiente manera.

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 Situación ideal si está utilizando .Net 3.5 –

+0

El primer fragmento de código funcionó para mí. Gran solución +1 –

+0

Tenga en cuenta que cada Remove() recorre la lista enlazada interna de elementos secundarios desde el primer hijo en adelante, por lo tanto, la complejidad computacional de cada eliminación es O (N). ¿Hay una forma O (1) de eliminar elementos? – redcalx

1

Cree una colección antes de la lógica de bucle, agregue los elementos que se van a eliminar a la nueva colección, luego llame a los elementos. Quite cada elemento de la colección nueva.

+0

Esto debería funcionar. Recuerdo haber hecho esto Mi respuesta probablemente no sea buena. Recuerdo algo acerca de si haces cambios en una lista o algo así, es una buena idea usarlo, pero si solo estás haciendo buches sin hacer ningún cambio, foreach está bien. ¿Es esto correcto? – Xaisoft

1

Pruébalo sin a en lugar de foreach.