c# .net collections comparison equality

c# - Comparando dos List<string> para la igualdad



.net collections (8)

Muchos frameworks de prueba ofrecen una clase CollectionAssert:

CollectionAssert.AreEqual(expected, actual);

Ej. MS Test

Además de recorrer los elementos uno por uno, ¿cómo puedo comparar dos listas de cadenas para la igualdad (en .NET 3.0):

Esto falla:

// Expected result. List<string> expected = new List<string>(); expected.Add( "a" ); expected.Add( "b" ); expected.Add( "c" ); // Actual result actual = new List<string>(); actual.Add( "a" ); actual.Add( "b" ); actual.Add( "c" ); // Verdict Assert.IsTrue( actual == expected );


Noté que nadie realmente te dijo por qué tu código original no funcionaba. Esto se debe a que el operador == en general prueba la igualdad de referencia (es decir, si las dos instancias apuntan al mismo objeto en la memoria) a menos que el operador haya sido overloaded . List<T> no define un operador == por lo que se usa la referencia base igual a la implementación.

Como han demostrado otros carteles, generalmente tendrá que pasar por elementos para probar la "igualdad de colección". Por supuesto, debe usar la optimización sugerida por el usuario DreamWalker que primero prueba el recuento de las colecciones antes de recorrerlas.


Podría escribir un método de extensión así:

public static class ListExtensions { public static bool IsEqual<T>(this IList<T> list,IList<T> target, IComparer<T> comparer) where T:IComparable<T> { if (list.Count != target.Count) { return false; } int index = 0; while (index < list.Count && comparer.Compare(list[index],target[index]) == 0) { index++; } if (index != list.Count) { return false; } return true; } }

Y llámalo así:

List<int> intList = new List<int> { 1, 234, 2, 324, 324, 2 }; List<int> targetList = new List<int> { 1, 234, 2, 324, 324 }; bool isEqual = intList.IsEqual(targetList, Comparer<int>.Default);

EDITAR: actualizó el código para usar un método estático en su lugar ya que OP está usando .NET 3.0

public static bool IsEqual<T>(IList<T> sourceList, IList<T> targetList, IComparer<T> comparer) where T : IComparable<T> { if (sourceList.Count != targetList.Count) { return false; } int index = 0; while (index < sourceList.Count && comparer.Compare(sourceList[index], targetList[index]) == 0) { index++; } if (index != sourceList.Count) { return false; } return true; }

Cliente:

bool isEqual = IsEqual(intList,targetList, Comparer<int>.Default);



Si bien itera sobre la colección, este método de extensión que he creado no requiere que el orden de las dos listas sea el mismo, y también funciona con tipos complejos, siempre que se anule el método Equals.

Las siguientes dos listas serían verdaderas:

List<string> list1 = new List<string> { { "bob" }, { "sally" }, { "john" } }; List<string> list2 = new List<string> { { "sally" }, { "john" }, { "bob" } };

Método:

public static bool IsEqualTo<T>(this IList<T> list1, IList<T> list2) { if (list1.Count != list2.Count) { return false; } List<T> list3 = new List<T>(); foreach (var item in list2) { list3.Add(item); } foreach (var item in list1) { int index = -1; for (int x = 0; x < list3.Count; x++) { if (list3[x].Equals(item)) { index = x; } } if (index > -1) { list3.RemoveAt(index); } else { return false; } } return !list3.Any(); }


Si el orden es importante:

bool equal = a.SequenceEquals(b);

Si el orden no importa:

bool equal = a.Count == b.Count && new HashSet<string>(a).SetEquals(b);


Siempre puede escribir la función necesaria por sí mismo:

public static bool ListEquals<T>(IList<T> list1, IList<T> list2) { if (list1.Count != list2.Count) return false; for (int i = 0; i < list1.Count; i++) if (!list1[i].Equals(list2[i])) return false; return true; }

y úsala:

// Expected result. List<string> expected = new List<string>(); expected.Add( "a" ); expected.Add( "b" ); expected.Add( "c" ); // Actual result actual = new List<string>(); actual.Add( "a" ); actual.Add( "b" ); actual.Add( "c" ); // Verdict Assert.IsTrue( ListEquals(actual, expected) );


Usando Linq y escribiendo el código como un método de extensión:

public static bool EqualsOtherList<T>(this List<T> thisList, List<T> theOtherList) { if (thisList == null || theOtherList == null || thisList.Count != theOtherList.Count) return false; return !thisList.Where((t, i) => !t.Equals(theOtherList[i])).Any(); }