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

C# 如何检查集合(>;2)的内容是否相同,c#,linq,C#,Linq,我有一张单子。出于正当理由,我多次复制该列表,并将其用于不同的目的。在某些时候,我需要检查所有这些集合的内容是否相同 我知道怎么做。但是作为一个“速记”编码(linq…)的爱好者,我想知道我是否能用最短的代码行数有效地检查这一点 List<string> original, duplicate1, duplicate2, duplicate3, duplicate4 = new List<st

我有一张单子。出于正当理由,我多次复制该列表,并将其用于不同的目的。在某些时候,我需要检查所有这些集合的内容是否相同

我知道怎么做。但是作为一个“速记”编码(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 
列出原件、副本1、副本2、副本3、副本4
=新列表(copy.All(y=>y.Remove(x)))
&&复制.All(n=>n.Count==0);
更新2

多亏了Eric,使用哈希集可以非常高效,如下所示。但这不包括重复的

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));
List copy2=new List{new HashSet(duplicate1),
新哈希集(重复2),
新哈希集(3),
新HashSet(duplicate4)};
HashSet origninalhashset=新的HashSet(原始);
bool eq=copy2.All(x=>origninalhashset.SetEquals(x));
更新3 多亏了Eric,本文中带有SequenceEqual的原始代码将用于排序。由于Sequenceequal将考虑集合的顺序,所以在调用序列相等之前,需要对集合进行排序。我想这不是什么大问题,因为排序非常快(nlogn)

更新4 根据Brian的建议,我可以使用查找

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)); 
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())));
var originallkup=original.ToLookup(i=>i);
var lookuplist=新列表
{4.ToLookup(i=>i),
重复3.ToLookup(i=>i),
2.ToLookup(i=>i),
重复1.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());

感谢大家的回复。

老实说,我想不出更有效的解决方案,但对于减少代码行数,请尝试一下:

var allLists = new List<List<string>>() { original, duplicate1, duplicate2, duplicate3, duplicate4 };

bool allEqual = allLists.All(l => l.SequenceEqual(original));
编辑:确认,
任何
确定值后将停止枚举源。多谢各位


EDIT#2:我一直在研究
SequenceEquals
的性能。将
SequenceEquals
与更重要的函数进行比较,这篇文章写得很好。我修改了他的例子来处理
列表
,我的发现与他的相符。就性能而言,
SequenceEquals
似乎在首选方法列表中并不高。

您可以使用反射创建通用比较器,并始终使用它。看看这个线程,它有很多代码可以帮助您:

我有一张单子。我多次复制该列表,并将其用于不同的目的。在某些时候,我需要检查所有这些集合的内容是否相同

一位评论者接着问道:


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

你的回答是:

只有内容才重要

在这种情况下,您首先使用了错误的数据结构。使用
散列集
,而不是
列表
,来表示无序的项集合,这些项集合必须进行廉价比较,以实现集合相等

一旦将所有内容都放在哈希集中而不是列表中,就可以简单地使用它们的
SetEquals
方法来查看是否有任何一对集合不相等


或者:将所有内容都保存在列表中,直到您希望比较是否相等为止。从其中一个列表初始化哈希集,然后使用SetEquals将该哈希集与其他列表进行比较。

顺序重要吗?或者仅仅是内容?@weston仅内容很重要“效率”或“代码行数最短”选择一个基本上你想检查列表是否与原始列表不同?@Jimmy:如果顺序不重要,但重复项很重要,那么你可以先对列表排序,然后再与SequenceEquals进行比较。这样,您就不会考虑顺序,而是保留了重复项。不确定
SequenceEquals
是否有引用相等的提前退出,但如果没有,手动检查将使代码更快一些。@CodeInChaos:谢谢,我没有考虑提前退出。我认为在这种情况下,
Any
可能是更好的选择。看我编辑过的答案。我不是说这种早退。我确信
All
已经做到了这一点。我的意思是
l=>(object.ReferenceEquals(l,original)| | l.sequenceequals(original)
。但我也不确定这是否必要。
All()
Any()
都足够聪明,可以在结果已知时停止。@tobias86-我认为你的代码可读性更强。效率与带有“and”的原始代码相当反射从何而来?使用泛型,看看帖子,你会明白的。@Vinicuius我查看了那边的所有解决方案,但没有看到任何反射。所以我不明白。例如,不是MethodInfo或Assembly.Load这样的代码,但泛型使用了这一概念。“您可以使用反射动态创建类型的实例,将类型绑定到现有对象[…]”-这就是我们使用泛型时发生的情况。@Eric您完全正确。我现在唯一关心的是重复(因为hashset不会接受重复)@吉米:使用字典将键映射到值。让键为项,值为计数。要检查内容是否相同,只需检查字典的长度是否匹配(这将告诉您不同元素的计数),然后对dict1中的每个键检查
dict2.TryGetValue(key,out count)&&count==dict1[key]
@Brian-如果我
bool allEqual = !allLists.Any(l => !l.SequenceEqual(original));