son - comparar elementos de una lista c#
La forma más rápida de comparar dos List<> (7)
¿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:
- ítems que aparecen en la primera lista, pero no en la segunda
- í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?
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<string> Contains(List<string> list1, List<string> list2)
{
List<string> result = new List<string>();
result.AddRange(list1.Except(list2, StringComparer.OrdinalIgnoreCase));
result.AddRange(list2.Except(list1, StringComparer.OrdinalIgnoreCase));
return result;
}
Más eficiente sería usar Except . 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<T>
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.
No es para este problema, pero aquí hay un código para comparar listas para iguales y no! objetos idénticos:
public class EquatableList<T> : List<T>, IEquatable<EquatableList<T>> where T : IEquatable<T>
/// <summary>
/// True, if this contains element with equal property-values
/// </summary>
/// <param name="element">element of Type T</param>
/// <returns>True, if this contains element</returns>
public new Boolean Contains(T element)
{
return this.Any(t => t.Equals(element));
}
/// <summary>
/// True, if list is equal to this
/// </summary>
/// <param name="list">list</param>
/// <returns>True, if instance equals list</returns>
public Boolean Equals(EquatableList<T> list)
{
if (list == null) return false;
return this.All(list.Contains) && list.All(this.Contains);
}
Puede ser divertido, pero funciona para mí
string.Join ("", List1)! = string.Join ("", List2)
Si desea que los resultados sean insensibles a las mayúsculas y minúsculas , lo siguiente funcionará:
List<string> list1 = new List<string> { "a.dll", "b1.dll" };
List<string> list2 = new List<string> { "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
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 declaración de devolución:
return !firstNotSecond.Any() && !secondNotFirst.Any();
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)));