如何检查集合(>;2)的内容是否相同
本文关键字:是否 gt 何检查 检查 集合 | 更新日期: 2023-09-27 18:23:49
我有一个列表。出于正当理由,我多次重复该清单,并将其用于不同的目的。在某个时刻,我需要检查所有这些集合的内容是否相同。
我知道怎么做。但作为"短手"编码(linq…)的粉丝,我想知道我是否可以用最短的代码行数来高效地检查这一点。
List<string> original, duplicate1, duplicate2, duplicate3, duplicate4
= new List<string();
//...some code.....
bool isequal = duplicate4.sequenceequal(duplicate3)
&& duplicate3.sequenceequal(duplicate2)
&& duplicate2.sequenceequal(duplicate1)
&& duplicate1.sequenceequal(original);//can we do it better than this
更新
Codeinchaos指出了我没有想到的某些情况(列表的重复和顺序)。虽然sequenceequal会处理重复,但列表的顺序可能是个问题。因此,我更改代码如下。我需要为此复制列表。
List<List<string>> copy = new List<List<int>> { duplicate1, duplicate2,
duplicate3, duplicate4 };
bool iseqaul = (original.All(x => (copy.All(y => y.Remove(x))))
&& copy.All(n => n.Count == 0));
更新2
多亏了Eric,使用HashSet可以非常高效,如下所示。不过,这不包括重复项。
List<HashSet<string>> copy2 =new List<HashSet<string>>{new HashSet<string>(duplicate1),
new HashSet<string>(duplicate2),
new HashSet<string> duplicate3),
new HashSet<string>(duplicate4)};
HashSet<string> origninalhashset = new HashSet<string>(original);
bool eq = copy2.All(x => origninalhashset.SetEquals(x));
更新3感谢Eric-这篇文章中使用SequenceEqual的原始代码将用于排序。由于Sequenceequal将考虑集合的顺序,因此在调用Sequenceequal之前需要对集合进行排序。我想这不是什么大问题,因为排序很快(nlogn)。
更新4根据Brian的建议,我可以使用查找。
var originallkup = original.ToLookup(i => i);
var lookuplist = new List<ILookup<int, int>>
{ duplicate4.ToLookup(i=> i),
duplicate3.ToLookup(i=> i),
duplicate2.ToLookup(i=> i),
duplicate1.ToLookup(i=> i)
};
bool isequal = (lookuplist.Sum(x => x.Count) == (originallkup.Count * 4)) &&
(originallkup.All(x => lookuplist.All(i => i[x.Key].Count() == x.Count())));
感谢大家的回复。
我有一份清单。我多次重复这份清单,并将其用于不同的目的。在某个时刻,我需要检查所有这些集合的内容是否相同。
一位评论者接着问道:
订单重要吗?还是仅仅是内容?
你的回答是:
只有内容才是重要的
在这种情况下,您首先使用了错误的数据结构。使用HashSet<T>
而不是List<T>
来表示无序的项集合,这些项必须进行廉价比较以获得集合相等性。
一旦你把所有的东西都放在散列集中而不是列表中,你就可以简单地使用它们的SetEquals
方法来查看是否有任何一对集合是不相等的。
或者:把所有的东西都放在列表中,直到你想比较是否相等为止。初始化其中一个列表中的哈希集,然后使用SetEquals将该哈希集与其他列表进行比较。
老实说,我想不出更有效的解决方案了,但关于减少代码行数,请抨击一下:
var allLists = new List<List<string>>() { original, duplicate1, duplicate2, duplicate3, duplicate4 };
bool allEqual = allLists.All(l => l.SequenceEqual(original));
或者,使用Any
运算符-在性能方面可能会更好。
bool allEqual = !allLists.Any(l => !l.SequenceEqual(original));
编辑:确认后,Any
将在确定值后停止枚举源。谢谢MSDN。
第2版:我一直在研究SequenceEquals
的性能。这家伙有一篇很好的帖子,把SequenceEquals
比作一个更为命令式的函数。我修改了他的例子以使用List<string>
,我的发现与他的相匹配。就性能而言,SequenceEquals
在首选方法列表中似乎并不高。
您可以使用反射来创建一个通用比较器,并始终使用它。看看这个线程,有很多代码可以帮助您:比较两个集合是否相等,而不考虑其中项目的顺序