有一个内置的方法来比较C#中的集合吗?

我想比较我的Equals方法中的几个集合的内容。 我有一个字典和一个IList。 有没有一个内置的方法来做到这一点?

编辑:我想比较两个词典和两个IList,所以我认为平等的含义是明确的 – 如果两个词典包含相同的键映射到相同的值,那么他们是平等的。

Enumerable.SequenceEqual

通过使用指定的IEqualityComparer(T)比较它们的元素来确定两个序列是否相等。

您不能直接比较列表和字典,但可以将“词典”中的值列表与列表进行比较

正如其他人所build议并注意到的, SequenceEqual是顺序敏感的。 为了解决这个问题,你可以通过键来sorting字典(这是唯一的,因此sorting总是稳定的),然后使用SequenceEqual 。 以下expression式检查两个字典是否相等,无论其内部顺序如何:

 dictionary1.OrderBy(kvp => kvp.Key).SequenceEqual(dictionary2.OrderBy(kvp => kvp.Key)) 

编辑:正如Jeppe Stig Nielsen所指出的那样,一些对象有一个与他们的IEqualityComparer<T>不兼容的IComparer<T> IEqualityComparer<T> ,产生不正确的结果。 对这样的对象使用键时,必须为这些键指定正确的IComparer<T> 。 例如,使用string键(出现此问题),您必须执行以下操作才能获得正确的结果:

 dictionary1.OrderBy(kvp => kvp.Key, StringComparer.Ordinal).SequenceEqual(dictionary2.OrderBy(kvp => kvp.Key, StringComparer.Ordinal)) 

除了提到的SequenceEqual之外 ,

如果两个列表的长度相等并且它们的相应元素根据比较器比较相等则为真

(这可能是默认的比较器,即重写Equals()

值得一提的是在.Net4中有ISet对象上的ISet

忽略元素和任何重复元素的顺序。

所以如果你想有一个对象列表,但是不需要按照特定的顺序,那么考虑一个ISet (比如HashSet )可能是正确的select。

看看Enumerable.SequenceEqual方法

 var dictionary = new Dictionary<int, string>() {{1, "a"}, {2, "b"}}; var intList = new List<int> {1, 2}; var stringList = new List<string> {"a", "b"}; var test1 = dictionary.Keys.SequenceEqual(intList); var test2 = dictionary.Values.SequenceEqual(stringList); 

.NET缺乏用于比较集合的强大工具。 我已经开发了一个简单的解决scheme,你可以在下面的链接find:

http://robertbouillon.com/2010/04/29/comparing-collections-in-net/

无论顺序如何,这将执行平等比较:

 var list1 = new[] { "Bill", "Bob", "Sally" }; var list2 = new[] { "Bob", "Bill", "Sally" }; bool isequal = list1.Compare(list2).IsSame; 

这将检查是否添加/删除项目:

 var list1 = new[] { "Billy", "Bob" }; var list2 = new[] { "Bob", "Sally" }; var diff = list1.Compare(list2); var onlyinlist1 = diff.Removed; //Billy var onlyinlist2 = diff.Added; //Sally var inbothlists = diff.Equal; //Bob 

这将看到字典中的项目改变:

 var original = new Dictionary<int, string>() { { 1, "a" }, { 2, "b" } }; var changed = new Dictionary<int, string>() { { 1, "aaa" }, { 2, "b" } }; var diff = original.Compare(changed, (x, y) => x.Value == y.Value, (x, y) => x.Value == y.Value); foreach (var item in diff.Different) Console.Write("{0} changed to {1}", item.Key.Value, item.Value.Value); //Will output: a changed to aaa 

我不知道Enumerable.SequenceEqual方法(你每天学习的东西….),但我会build议使用扩展方法; 像这样的东西:

  public static bool IsEqual(this List<int> InternalList, List<int> ExternalList) { if (InternalList.Count != ExternalList.Count) { return false; } else { for (int i = 0; i < InternalList.Count; i++) { if (InternalList[i] != ExternalList[i]) return false; } } return true; } 

有趣的是,花了2秒时间阅读了关于SequenceEqual,看起来像微软已经build立了我为你描述的function。

这不是直接回答你的问题,而是MS的TestTools和NUnit提供的

  CollectionAssert.AreEquivalent 

这几乎是你想要的。

为了比较collections,你也可以使用LINQ。 Enumerable.Intersect返回所有相等的对。 你可以像这样压缩两个字典:

 (dict1.Count == dict2.Count) && dict1.Intersect(dict2).Count() == dict1.Count 

第一个比较是需要的,因为dict2可以包含dict1和更多的所有关键字。

您也可以使用Enumerable.ExceptEnumerable.Union来使用变体,这会导致类似的结果。 但是可以用来确定集合之间的确切区别。

这个例子如何:

  static void Main() { // Create a dictionary and add several elements to it. var dict = new Dictionary<string, int>(); dict.Add("cat", 2); dict.Add("dog", 3); dict.Add("x", 4); // Create another dictionary. var dict2 = new Dictionary<string, int>(); dict2.Add("cat", 2); dict2.Add("dog", 3); dict2.Add("x", 4); // Test for equality. bool equal = false; if (dict.Count == dict2.Count) // Require equal count. { equal = true; foreach (var pair in dict) { int value; if (dict2.TryGetValue(pair.Key, out value)) { // Require value be equal. if (value != pair.Value) { equal = false; break; } } else { // Require key be present. equal = false; break; } } } Console.WriteLine(equal); } 

礼貌: https : //www.dotnetperls.com/dictionary-equals

不。收集框架没有任何平等的概念。 如果你仔细想一想,就没有办法比较那些不是主观的collections。 比如把你的IList和你的词典进行比较,如果所有的键都在IList中,那么所有的值都在IList中,还是都在IList中? 没有明显的方式来比较这两个集合,而不知道它们将被用于什么,所以一个通用的equals方法是没有意义的。

不,因为框架不知道如何比较列表的内容。

看看这个:

http://blogs.msdn.com/abhinaba/archive/2005/10/11/479537.aspx

 public bool CompareStringLists(List<string> list1, List<string> list2) { if (list1.Count != list2.Count) return false; foreach(string item in list1) { if (!list2.Contains(item)) return false; } return true; }