Diferencia entre dos listas

Tengo dos listas genéricas rellenas con CustomsObjects.

Necesito recuperar la diferencia entre esas dos listas (elementos que están en la primera sin los elementos en la segunda) en una tercera.

Estaba pensando en utilizar .Except() era una buena idea, pero no veo cómo usar esto … ¡Ayuda!

Usar Except es exactamente el camino correcto a seguir. Si su tipo anula Equals y GetHashCode , o si solo está interesado en la igualdad del tipo de referencia (es decir, dos referencias son solo “iguales” si se refieren al mismo objeto exacto), puede usar:

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

Si necesita express una idea personalizada de igualdad, por ejemplo, mediante ID, deberá implementar IEqualityComparer . Por ejemplo:

 public class IdComparer : IEqualityComparer { public int GetHashCode(CustomObject co) { if (co == null) { return 0; } return co.Id.GetHashCode(); } public bool Equals(CustomObject x1, CustomObject x2) { if (object.ReferenceEquals(x1, x2)) { return true; } if (object.ReferenceEquals(x1, null) || object.ReferenceEquals(x2, null)) { return false; } return x1.Id == x2.Id; } } 

Luego usa:

 var list3 = list1.Except(list2, new IdComparer()).ToList(); 

Tenga en cuenta que esto eliminará cualquier elemento duplicado. Si necesita duplicados para preservar, probablemente sería más fácil crear un conjunto de list2 y usar algo como:

 var list3 = list1.Where(x => !set2.Contains(x)).ToList(); 

Podrías hacer algo como esto:

 var result = customlist.Where(p => !otherlist.Any(l => p.someproperty == l.someproperty)); 
 var third = first.Except(second); 

(También puede llamar a ToList() después de Except() , si no le gusta hacer referencia a las colecciones perezosas).

El método Except() compara los valores usando el comparador predeterminado, si los valores que se comparan son de tipos de datos base, como int , string , decimal , etc.

De lo contrario, la comparación se realizará por dirección de objeto, que probablemente no sea la que usted desea … En ese caso, haga que sus objetos personalizados implementen IComparable (o implemente un IEqualityComparer personalizado y páselo al método Except() ).

Dado que el método de extensión Except opera en dos IEaerables, me parece que será una operación O (n ^ 2). Si el rendimiento es un problema (si tus listas son grandes), te sugiero que crees un HashSet de list1 y uses el método ExceptWith de HashSet.

Creo que es importante destacar que el uso del método Except te devolverá elementos que están en el primero sin los artículos en el segundo. No devuelve esos elementos en el segundo que no aparecen en primer lugar.

 var list1 = new List { 1, 2, 3, 4, 5}; var list2 = new List { 3, 4, 5, 6, 7 }; var list3 = list1.Except(list2).ToList(); //list3 contains only 1, 2 

Pero si quiere obtener una diferencia real entre dos listas:

Artículos que están en el primero sin los artículos en el segundo y los artículos que están en el segundo sin los artículos en el primero.

Necesita usar Excepto dos veces:

 var list1 = new List { 1, 2, 3, 4, 5}; var list2 = new List { 3, 4, 5, 6, 7 }; var list3 = list1.Except(list2); //list3 contains only 1, 2 var list4 = list2.Except(list1); //list4 contains only 6, 7 var resultList = list3.Concat(list4).ToList(); //resultList contains 1, 2, 6, 7 

O puede usar el método SymmetricExcerptWith de HashSet. Pero cambia el conjunto en el que se llama:

 var list1 = new List { 1, 2, 3, 4, 5}; var list2 = new List { 3, 4, 5, 6, 7 }; var list1Set = list1.ToHashSet(); //.net framework 4.7.1 and .net core 2.0 and above otherwise new HashSet(list1) list1Set.SymmetricExceptWith(list2); var resultList = list1Set.ToList(); //resultList contains 1, 2, 6, 7 

Si ambas listas implementan la interfaz IEnumerable, puede lograr esto utilizando LINQ.

 list3 = list1.where(i => !list2.contains(i)); 

un poco tarde, pero aquí está la solución de trabajo para mí

  var myBaseProperty = (typeof(BaseClass)).GetProperties();//get base code properties var allProperty = entity.GetProperties()[0].DeclaringType.GetProperties();//get derived class property plus base code as it is derived from it var declaredClassProperties = allProperty.Where(x => !myBaseProperty.Any(l => l.Name == x.Name)).ToList();//get the difference 

En el código mencionado anteriormente, obtengo la diferencia de propiedades entre mi clase base y la lista de clases derivadas

  List list1 = new List(); List list2 = new List(); List listDifference = new List(); foreach (var item1 in list1) { foreach (var item2 in list2) { if (item1 != item2) listDifference.Add(item1); } }