如何检查集合(>;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())));

感谢大家的回复。

如何检查集合(>;2)的内容是否相同

我有一份清单。我多次重复这份清单,并将其用于不同的目的。在某个时刻,我需要检查所有这些集合的内容是否相同。

一位评论者接着问道:

订单重要吗?还是仅仅是内容?

你的回答是:

只有内容才是重要的

在这种情况下,您首先使用了错误的数据结构。使用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在首选方法列表中似乎并不高。

您可以使用反射来创建一个通用比较器,并始终使用它。看看这个线程,有很多代码可以帮助您:比较两个集合是否相等,而不考虑其中项目的顺序