2012-02-15 24 views
7

Lamento publicar tales preguntas básicas, soy nuevo en LINQ y estoy tratando de encontrar la mejor manera de hacer esto sin hacer un bucle en cada IList.Eliminar elementos en un IList <> de otro IList <>

Tengo 2 ILists<> con objetos dto personalizados. Quiero eliminar todos los elementos coincidentes de la lista que están en la otra.

IList<ItemDTO> list1 = itemsbl.GetBestItems(); 
IList<ItemDTO> list2 = itemsbl.GetWorstItems(); 

necesito para eliminar todos los elementos de list1 de list2. He estado buscando en el método Except(), pero aparentemente necesito mi clase ItemsDTO para anular los métodos GetHashCode y Equals para que funcione, pero tengo problemas para encontrar algunos ejemplos de esto.

¿Podría alguien mostrarme la mejor manera de eliminar list1 de list2?

Gracias de nuevo

Respuesta

9

Probablemente se puede utilizar el método de excepción para hacer esto.

var newList = list2.Except(list1).ToList(); 

Si desea reemplazar lista2 luego simplemente hacer esto:

list2 = list2.Except(list1).ToList(); 

De MSDN:

para comparar tipos de datos personalizados, implementar el IEquatable interfaz genérica y proporcionar su propia Métodos GetHashCode e Igual para el tipo . El comparador de igualdad predeterminado, Predeterminado, se usa para comparar los valores de los tipos que implementan IEquatable.

+0

Gracias, acabé modificando mi clase en consecuencia para que pueda EE.UU., excepto() ... Gracias a todos, estoy seguro que todos los demás soluciones eran tan bueno ...:) – Nugs

1

Hash it definitivamente una buena manera, @Jon Skeet a continuación la respuesta a una pregunta similar le proporcionará la solución.

así que básicamente es la sintaxis:

var setToRemove = new HashSet<ItemDTO>(list1); 
list2.RemoveAll(x => setToRemove.Contains(x)); 

Using LINQ to remove elements from a List<T>

espero que esto ayude.

+0

No sé por qué, pero RemoveAll() no es una opción para mí ... – Nugs

+3

IList es la interfaz que List implementa.IList se utiliza para otras clases de colección. La clase List contiene métodos que pueden no estar definidos en IList. Entonces al asignar su objeto de lista original a IList ya no tendrá acceso a ningún método único de List. A menos que tenga una razón para usar IList , recomendaría usar la lista . MSDN: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx – Nickz

1
var list1 = new List<string> { "A", "B", "C" }; 
var list2 = new List<string> { "A", "C", "E", "B", "D", "G", "F" }; 
list2.RemoveAll(list1.Contains); 

funcionarán también. Tenga en cuenta que la lista1.Contiene es en realidad una lambda

s => list1.Contains(s) 

-A.

+0

No sé por qué, pero RemoveAll() no es una opción para mí ... – Nugs

+0

'list.Contains' no es en realidad una lambda. Aunque se comporta de la misma manera aquí. – svick

+1

Mencioné esto porque pensé que era importante que RemoveAll tomara un predicado, especialmente dado que los objetos del OP podrían no tener implementada la igualdad/comparación. – Ani

0

Lo que significa es que necesita decirle al tiempo de ejecución .net cómo determinar si dos instancias de una clase son iguales (por ejemplo, cómo debería definir si una instancia de ItemDTO es igual a otra instancia de ItemDTO).

Para ello, es igual de anulación

public class ItemDTO 
{ 
    public override bool Equals(object obj) 
    { 
     var otherItem = obj as ItemDTO; 

     if (otherItem == null) 
     { 
      // this will be because either 'obj' is null or it is not of type ItemDTO. 
      return false; 
     } 

     return otherItem.SomeProperty == this.SomeProperty 
       && otherItem.OtherProperty == this.OtherProperty; 
    } 
} 

Si no lo hace, sólo se eliminará cualquier referencia en la lista que apuntan a la misma instancia física como la otra. Luego puede usar los métodos Except o RemoveAll o cualquier otro método que decida usar.

También tendrá que anular GetHashcode, consulte el enlace a continuación para obtener más información al respecto.

Ver Guidelines for Overloading Equals and GetHashcode

Cuestiones relacionadas