Сравнение двух списков для равенства
кроме пошагового перебора элементов один за другим, как сравнить два списка строк для равенства (в .NET 3.0):
Это не удается:
// 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 );
8 ответов:
многие тестовые платформы предлагают класс CollectionAssert:
CollectionAssert.AreEqual(expected, actual);например MS Test
попробуйте следующее
var equal = expected.SequenceEqual(actual);Тестовая Версия
Assert.IsTrue( actual.SequenceEqual(expected) );метод расширения SequenceEqual будет сравнивать элементы коллекции для обеспечения равенства.
посмотреть http://msdn.microsoft.com/en-us/library/bb348567(в=против 100).аспн
вы всегда можете написать необходимую функцию сами:
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; }и использовать его:
// 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) );
Я заметил, что никто на самом деле не сказал вам, почему ваш исходный код не работает. Это потому что
==оператор в общих тестах равенство ссылок (т. е. если два экземпляра указывают на один и тот же объект в памяти), если оператор перегружен.List<T>не определяет==оператор таким образом, базовая ссылка равна реализации используется.как показали другие плакаты, вам, как правило, придется пройти элементы для проверки " равенство коллекций."Конечно, вы должны использовать оптимизацию, предложенную пользователем DreamWalker, который сначала проверяет количество коллекций, прежде чем шагать через них.
Если порядок имеет значение:
bool equal = a.SequenceEquals(b);если заказ не имеет значения:
bool equal = a.Count == b.Count && new HashSet<string>(a).SetEquals(b);
вы можете написать метод расширения следующим образом:
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; } }и назовем это так:
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);редактировать: обновлен код, чтобы использовать статический метод, поскольку ОП является использование .Чистая 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; }клиент:
bool isEqual = IsEqual(intList,targetList, Comparer<int>.Default);
использование Linq и написание кода в качестве метода расширения:
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(); }
хотя он выполняет итерацию по коллекции, этот метод расширения, который я создал, не требует, чтобы порядок двух списков был одинаковым, и он также работает со сложными типами, если метод Equals переопределен.
следующие два списка вернут true:
List<string> list1 = new List<string> { { "bob" }, { "sally" }, { "john" } }; List<string> list2 = new List<string> { { "sally" }, { "john" }, { "bob" } };способ:
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(); }
Comments