当前位置:  开发笔记 > 编程语言 > 正文

是否有内置的方法来比较集合?

如何解决《是否有内置的方法来比较集合?》经验,为你挑选了5个好方法。

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

编辑:我想比较两个字典和两个IList,所以我认为平等意味着什么是明确的 - 如果两个字典包含映射到相同值的相同键,那么它们是相等的.



1> Glenn Slaven..:

Enumerable.SequenceEqual

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

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


问题是SequenceEqual期望元素的顺序相同.在枚举时,Dictionary类不保证键或值的顺序,因此如果您要使用SequenceEqual,则必须先对.Keys和.Values进行排序!
@schoetbi:为什么要检测*不保证订单*的容器中的订购差异?
MS'TestTools和NUnit提供CollectionAssert.AreEquivalent
@schoetbi:它是从IEnumerable中取出某个元素的.但是,字典不保证顺序,因此`.Keys`和`.Values`可以按照他们的任何顺序返回键和值,并且该顺序可能会随着字典的修改而改变.我建议你阅读一下字典是什么,不是什么.
@Orion:...除非你想检测订购差异,当然:-)

2> Allon Guraln..:

正如其他人所建议并注意到的那样,对SequenceEqual订单敏感.要解决这个问题,您可以按键对字典进行排序(这是唯一的,因此排序总是稳定的)然后使用SequenceEqual.以下表达式检查两个字典是否相等,无论其内部顺序如何:

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

编辑:正如Jeppe Stig Nielsen指出的那样,某些物体IComparer与它们不相容IEqualityComparer,产生了不正确的结果.使用具有此类对象的键时,必须IComparer为这些键指定正确的键.例如,使用字符串键(显示此问题),您必须执行以下操作才能获得正确的结果:

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



3> Desty..:

除了提到的SequenceEqual,这

如果两个列表长度相等且它们的对应元素根据比较器进行比较,则为true

(可能是默认的比较器,即覆盖Equals())

值得一提的是,在.NET4有SetEquals的ISet对象,

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

因此,如果您想要一个对象列表,但它们不需要按特定顺序排列,请考虑ISet(如a HashSet)可能是正确的选择.



4> aku..:

看一下Enumerable.SequenceEqual 方法

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


这是不可靠的,因为SequenceEqual期望值以可靠的顺序出现在字典中 - 字典对命令没有这样的保证,而字典.Keys很可能出现为[2,1]而不是[1,2]而你的测试会失败

5> 小智..:

.NET缺乏用于比较集合的强大工具.我开发了一个简单的解决方案,您可以在以下链接中找到:

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() { { 1, "a" }, { 2, "b" } };
var changed = new Dictionary() { { 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


当然,.NET有比较集合的强大工具(它们是基于集合的操作).`.Removed`与`list1.Except(list2)`相同,`.Added`是`list2.Except(list1)`,`.Equal`是`list1.Intersect(list2)`和`.Different`是`original.Join(更改,左=> left.Key,右=> right.Key,(左,右)=> left.Value == right.Value)`.您几乎可以与LINQ进行任何比较.
更正:`.Different`是`original.Join(更改,左=> left.Key,right => right.Key,(左,右)=> new {Key = left.Key,NewValue = right.Value,Different = left.Value == right.Value).其中(d => d.Different)`.如果你还需要旧值,你甚至可以添加`OldValue = left.Value`.
@AllonGuralnek你的建议很好,但他们没有处理List不是真集的情况 - 列表中多次包含同一个对象.比较{1,2}和{1,2,2}将不会返回任何添加/删除的内容.
http://robertbouillon.com/似乎已经失踪,最终得到了GoDaddy.
推荐阅读
sx-March23
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有