La forma más rápida de comparar dos List

¿Cuál es el método más rápido (y menos intensivo en recursos) para comparar dos elementos masivos (> 50,000) y, como resultado, tiene dos listas como las siguientes:

  1. ítems que aparecen en la primera lista, pero no en la segunda
  2. ítems que aparecen en la segunda lista pero no en la primera

Actualmente estoy trabajando con List o IReadOnlyCollection y resuelvo este problema en una consulta de linq:

var list1 = list.Where(i => !list2.Contains(i)).ToList(); var list2 = list2.Where(i => !list.Contains(i)).ToList(); 

Pero esto no funciona tan bien como me gustaría. ¿Alguna idea de hacer esto más rápido y menos intensivo de recursos ya que necesito procesar muchas listas?

Use Except :

 var firstNotSecond = list1.Except(list2).ToList(); var secondNotFirst = list2.Except(list1).ToList(); 

Sospecho que hay enfoques que en realidad serían marginalmente más rápidos que esto, pero incluso esto será mucho más rápido que tu enfoque O (N * M).

Si desea combinar estos, puede crear un método con la anterior y luego una statement de devolución:

 return !firstNotSecond.Any() && !secondNotFirst.Any(); 

Más eficiente sería usar Enumerable.Except . Enumerable.Except :

 var inListButNotInList2 = list.Except(list2); var inList2ButNotInList = list2.Except(list); 

Este método se implementa mediante el uso de la ejecución diferida. Eso significa que podrías escribir, por ejemplo:

 var first10 = inListButNotInList2.Take(10); 

También es eficiente ya que internamente usa un Set para comparar los objetos. Funciona al recoger primero todos los valores distintos de la segunda secuencia, y luego transmitir los resultados de la primera, comprobando que no se hayan visto antes.

Si desea que los resultados sean insensibles a las mayúsculas y minúsculas , lo siguiente funcionará:

 List list1 = new List { "a.dll", "b1.dll" }; List list2 = new List { "A.dll", "b2.dll" }; var firstNotSecond = list1.Except(list2, StringComparer.OrdinalIgnoreCase).ToList(); var secondNotFirst = list2.Except(list1, StringComparer.OrdinalIgnoreCase).ToList(); 

firstNotSecond contendría b1.dll

secondNotFirst contendría b2.dll

No es para este problema, pero aquí hay un código para comparar listas para iguales y no! objetos idénticos:

 public class EquatableList : List, IEquatable> where T : IEquatable ///  /// True, if this contains element with equal property-values ///  /// element of Type T /// True, if this contains element public new Boolean Contains(T element) { return this.Any(t => t.Equals(element)); } ///  /// True, if list is equal to this ///  /// list /// True, if instance equals list public Boolean Equals(EquatableList list) { if (list == null) return false; return this.All(list.Contains) && list.All(this.Contains); } 

intente de esta manera:

 var difList = list1.Where(a => !list2.Any(a1 => a1.id == a.id)) .Union(list2.Where(a => !list1.Any(a1 => a1.id == a.id))); 

He usado este código para comparar dos listas que tienen un millón de registros.

Este método no tomará mucho tiempo

  //Method to compare two list of string private List Contains(List list1, List list2) { List result = new List(); result.AddRange(list1.Except(list2, StringComparer.OrdinalIgnoreCase)); result.AddRange(list2.Except(list1, StringComparer.OrdinalIgnoreCase)); return result; } 

Esta es la mejor solución que encontrarás

 var list3 = list1.Where(l => llist2.ToList().Contains(l)); 

Puede ser divertido, pero funciona para mí

string.Join (“”, List1)! = string.Join (“”, List2)