Comparing two List for equality
除了一步一步地处理这些元素之外,如何比较两个相等的字符串列表(在.NET 3.0中):
这将失败:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
尝试以下
1 | var equal = expected.SequenceEqual(actual); |
测试版本
1 | Assert.IsTrue( actual.SequenceEqual(expected) ); |
SequenceEqual扩展方法将比较集合中的元素,以确保相等。
参见http://msdn.microsoft.com/zh-cn/library/bb348567(v=vs.100).aspx
许多测试框架都提供CollectionAssert类:
1 | CollectionAssert.AreEqual(expected, actual); |
例如MS测试
您总是可以自己编写所需的函数:
1 2 3 4 5 6 7 8 | 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; } |
并使用它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
我注意到没有人真正告诉过您为什么原始代码无法正常工作。这是因为
正如其他张贴者所展示的那样,您通常必须逐步通过一些要素来测试"集合相等性"。当然,您应该使用DreamWalker用户建议的优化方法,该优化程序在逐步检查集合之前先测试集合的计数。
如果订单很重要:
1 | bool equal = a.SequenceEquals(b); |
如果顺序无关紧要:
1 |
使用Linq并将代码编写为扩展方法:
1 2 3 4 5 6 | 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(); } |
您可以这样编写扩展方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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; } } |
并这样称呼它:
1 2 3 |
编辑:更新代码以改为使用静态方法,因为OP使用的是.NET 3.0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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; } |
客户:
1 | bool isEqual = IsEqual(intList,targetList, Comparer<int>.Default); |
可能以非常规方式使用它,但没有为自定义类型实现IEquatable
1 | JsonConvert.SerializeObject( myList1) == JsonConvert.SerializeObject( myList2) |
但通常情况下,您可以使用注释https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.enumerable.sequenceequal?view=netframework-4.8中提到的SequenceEqual
另外,不要忘记为自定义类型实现IEquatable接口(对于字符串类型或其他结构不是必需的)
尽管它确实遍历集合,但是我创建的此扩展方法不需要两个列表的顺序相同,并且只要覆盖Equals方法,它也可以用于复杂类型。
以下两个列表将返回true:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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(); } |