2010-07-06 22 views
43

Tengo 2 colecciones de IEnumerable.Eliminar elementos de IEnumerable <T>

IEnumerable<MyClass> objectsToExcept 

y

IEnumerable<MyClass> allObjects. 

objectsToExcept puede contener objetos de allObjects.

Necesito eliminar de allObjects objetos en objectsToExcept. Por ejemplo:

foreach (var myClass in objectsToExcept) 
{ 
allObjects.Remove(myClass); 
} 

O

allObject.Except(objectsToExcept) 

Pero no funciona. El recuento posterior a la ejecución de los métodos indica que no se han eliminado elementos.

Respuesta

58

No veo cómo se compilaría la primera versión, y la segunda versión no hará nada a menos que use el resultado. No elimina nada de la colección existente; de ​​hecho, puede que ni siquiera sea una colección en memoria que la respalde. Simplemente devuelve una secuencia que, cuando se repite, devolverá los valores apropiados.

Si son utilizando el resultado, p.

IEnumerable<MyClass> others = allObjects.Except(objectsToExcept); 
foreach (MyClass x in others) 
{ 
    ... 
} 

entonces debería estar bien si se ha redefinido GetHashCode y Equals o si estás dispuesto a utilizar la igualdad de referencia. ¿Está tratando de eliminar valores lógicamente iguales, o hacer las mismas referencias que ocurren en ambas secuencias? ¿Ha anulado GetHashCode y Equals? De ser así, ¿está seguro de que esas implementaciones funcionan?

Básicamente debería estar bien, le sugiero que intente crear un programa breve pero completo que demuestre el problema; Sospecho que, al hacerlo, descubrirás lo que está mal.

16

Eliminar y excepto no modificar el IEnumerable original. Ellos devuelven uno nuevo. tratar

var result = allObject.Except(objectsToexcept); 
28

No hay Remove método de IEnumerable<T>, ya que no está destinado a ser modificable.

El método Except no modifica la colección original: devuelve una nueva colección que no contiene los elementos excluidos:

var notExcluded = allObjects.Except(objectsToExcept); 

Ver Except en MSDN.

+4

'Eliminar' existe como un método de extensión en el espacio de Linq a XML, pero no hace lo que el OP intenta hacer. Curiosamente lo ves en la página de documentación para los miembros de 'IEnumerable ' pero tiene una restricción 'donde T: XNode'. Técnicamente 'Except' no está en 'IEnumerable ' tampoco, pero eso es absolutamente demasiado quisquilloso. –

+1

@Mike Dos, de hecho, nunca me di cuenta de que ... parece un error en la documentación –

3

Mientras que las otras respuestas son correctas, debo agregar que el resultado de la llamada Except() se puede volver a asignar a la variable original.Es decir,

allObjects = allObjects.Except(objectsToExcept); 

También hay que tener en cuenta que Except() producirá la diferencia conjunto de las dos colecciones, así que si hay duplicados de las variables a ser removidos, todos ellos serán eliminados.

0
others.Where(contract => !objectsToExcept.Any()).ToList(); 
Cuestiones relacionadas