una two son otra objetos lists listas lista iguales equal eliminar elementos duplicados comparar buscar are c# list comparison equals

son - compare if two lists are equal c#



Compare dos objetos de lista<T> para la igualdad, ignorando el orden (10)

Otra pregunta que compara listas.

List<MyType> list1; List<MyType> list2;

Necesito verificar que ambos tengan los mismos elementos, independientemente de su posición dentro de la lista. Cada objeto MyType puede aparecer varias veces en una lista. ¿Hay una función incorporada que comprueba esto? ¿Qué pasa si garantizo que cada elemento aparece solo una vez en una lista?

EDIT: Gracias por las respuestas, pero me olvidé de agregar algo, el número de ocurrencias de cada elemento debería ser el mismo en ambas listas.


Responder

Combine Count , Except y Any like this. Como mencionó Bioukh, es más rápido Count primero.

public static bool AreTheSameIgnoringOrder(List<string> x, List<string> y) { return x.Count() == y.Count() && !x.Except(y).Any() && !y.Except(x).Any(); // re: Servy''s comment. }

Manifestación

Aquí hay un violín para demostrar.

using System; using System.Collections.Generic; using System.Linq; public class Program { public static void Main() { var x = new List<string>() { "a", "b", "c"}; var result1 = AreTheSameIgnoringOrder(x, new List<string>() { "c", "b", "a"}); Console.WriteLine(result1); var result2 = AreTheSameIgnoringOrder(x, new List<string>() { "c", "b", "a", "b" }); Console.WriteLine(result2); } public static bool AreTheSameIgnoringOrder(List<string> x, List<string> y) { return x.Count() == y.Count() && !x.Except(y).Any() && !y.Except(x).Any(); } }


¡¡¡prueba esto!!!

utilizando el siguiente código, puede comparar uno o varios campos para generar una lista de resultados según su necesidad. la lista de resultados contendrá solo artículos modificados.

// veriables been used List<T> diffList = new List<T>(); List<T> gotResultList = new List<T>(); // compare First field within my MyList gotResultList = MyList1.Where(a => !MyList2.Any(a1 => a1.MyListTField1 == a.MyListTField1)).ToList().Except(gotResultList.Where(a => !MyList2.Any(a1 => a1.MyListTField1 == a.MyListTField1))).ToList(); // Generate result list diffList.AddRange(gotResultList); // compare Second field within my MyList gotResultList = MyList1.Where(a => !MyList2.Any(a1 => a1.MyListTField2 == a.MyListTField2)).ToList().Except(gotResultList.Where(a => !MyList2.Any(a1 => a1.MyListTField2 == a.MyListTField2))).ToList(); // Generate result list diffList.AddRange(gotResultList); MessageBox.Show(diffList.Count.ToString);


Además de la respuesta de Guffa, puedes usar esta variante para tener una notación más abreviada.

public static bool ScrambledEquals<T>(this IEnumerable<T> list1, IEnumerable<T> list2) { var deletedItems = list1.Except(list2).Any(); var newItems = list2.Except(list1).Any(); return !newItems && !deletedItems; }


Como está escrito, esta pregunta es ambigua. La declaración:

... ambos tienen los mismos elementos, independientemente de su posición dentro de la lista. Cada objeto MyType puede aparecer varias veces en una lista.

no indica si desea asegurarse de que las dos listas tengan el mismo conjunto de objetos o el mismo conjunto distinto .

Si desea asegurarse de que las colecciones tengan exactamente el mismo conjunto de miembros, independientemente del orden, puede utilizar:

// lists should have same count of items, and set difference must be empty var areEquivalent = (list1.Count == list2.Count) && !list1.Except(list2).Any();

Si desea asegurarse de que dos colecciones tengan el mismo conjunto de miembros (donde se ignoran los duplicados), puede usar:

// check that [(A-B) Union (B-A)] is empty var areEquivalent = !list1.Except(list2).Union( list2.Except(list1) ).Any();

Usar las operaciones establecidas ( Intersect , Union , Except ) es más eficiente que usar métodos como Contains . En mi opinión, también expresa mejor las expectativas de su consulta.

EDITAR: Ahora que ha aclarado su pregunta, puedo decir que desea utilizar el primer formulario, ya que los duplicados son importantes. Aquí hay un ejemplo simple para demostrar que obtiene el resultado que desea:

var a = new[] {1, 2, 3, 4, 4, 3, 1, 1, 2}; var b = new[] { 4, 3, 2, 3, 1, 1, 1, 4, 2 }; // result below should be true, since the two sets are equivalent... var areEquivalent = (a.Count() == b.Count()) && !a.Except(b).Any();


Este es un problema ligeramente difícil, que creo que se reduce a: "Probar si dos listas son permutaciones entre sí".

Creo que las soluciones proporcionadas por otros solo indican si las 2 listas contienen los mismos elementos únicos . Esta es una prueba necesaria pero insuficiente, por ejemplo {1, 1, 2, 3} no es una permutación de {3, 3, 1, 2} aunque sus conteos son iguales y contienen los mismos elementos distintos.

Creo que esto debería funcionar, aunque no es el más eficiente:

static bool ArePermutations<T>(IList<T> list1, IList<T> list2) { if(list1.Count != list2.Count) return false; var l1 = list1.ToLookup(t => t); var l2 = list2.ToLookup(t => t); return l1.Count == l2.Count && l1.All(group => l2.Contains(group.Key) && l2[group.Key].Count() == group.Count()); }


Esto funcionó para mí:
Si está comparando dos listas de objetos que dependen de una sola entidad como ID , y desea una tercera lista que coincida con esa condición, puede hacer lo siguiente:

list3=List1.Where(n => !List2.select(n1 => n1.Id).Contains.(n.Id));

Consulte: MSDN - C # Comparar dos listas de objetos


Pensando que esto debería hacer lo que quieres:

list1.All(item => list2.Contains(item)) && list2.All(item => list1.Contains(item));

Si quieres que sea distinto, puedes cambiarlo a:

list1.All(item => list2.Contains(item)) && list1.Distinct().Count() == list1.Count && list1.Count == list2.Count


Si desea que sean realmente iguales (es decir, los mismos elementos y el mismo número de cada uno), creo que la solución más sencilla es ordenar antes de comparar:

Enumerable.SequenceEqual(list1.OrderBy(t => t), list2.OrderBy(t => t))

Editar:

Aquí hay una solución que funciona un poco mejor (unas diez veces más rápido), y solo requiere IEquatable , no IComparable :

public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2) { var cnt = new Dictionary<T, int>(); foreach (T s in list1) { if (cnt.ContainsKey(s)) { cnt[s]++; } else { cnt.Add(s, 1); } } foreach (T s in list2) { if (cnt.ContainsKey(s)) { cnt[s]--; } else { return false; } } return cnt.Values.All(c => c == 0); }

Edición 2:

Para manejar cualquier tipo de datos como clave (por ejemplo, tipos anulables como señala Frank Tzanabetis), puede hacer una versión que tome un comparer para el diccionario:

public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2, IEqualityComparer<T> comparer) { var cnt = new Dictionary<T, int>(comparer); ...


Si no te importa el número de incidencias, lo abordaría así. El uso de conjuntos hash le dará un mejor rendimiento que una simple iteración.

var set1 = new HashSet<MyType>(list1); var set2 = new HashSet<MyType>(list2); return set1.SetEquals(set2);

Esto requerirá que hayas anulado .GetHashCode() e implementado IEquatable<MyType> en MyType .


Yo uso este método)

public delegate bool CompareValue<in T1, in T2>(T1 val1, T2 val2); public static bool CompareTwoArrays<T1, T2>(this IEnumerable<T1> array1, IEnumerable<T2> array2, CompareValue<T1, T2> compareValue) { return array1.Select(item1 => array2.Any(item2 => compareValue(item1, item2))).All(search => search) && array2.Select(item2 => array1.Any(item1 => compareValue(item1, item2))).All(search => search); }