2010-09-21 72 views
6

我知道LINQ有一个SequenceEquals方法。此方法确保每个集合中的每个项目值都以相同的顺序匹配。有没有LINQ等价的方法?

我在找的是一个更“等同”的功能类型。只是这两个序列包含相同的项目,不一定按相同的顺序。

例如,nUnit有CollectionAssert.AreEqual()CollectionAssert.AreEquivalent()可以做我正在解释的。

我知道,我可以通过这样做:

  1. 提前订购名单,并使用SequenceEquals
  2. 使用Intersect,然后看是否交点等于原序列。

例子:

var source = new[] {5, 6, 7}; 
source.Intersect(new[] {5, 7, 6}).Count() == source.Length; 
+1

有回答的例子是错误的。您需要将其与两种计数进行比较,否则当源是目标的子集时,您的函数将返回“真”。即源{5,6}和目标{5,7,6} – cellik 2013-11-13 11:50:26

回答

8

我会创建一个扩展方法来完成相交,然后比较计数。

+0

您可以得到答案给我的想法来比较计数,所以它使它更好,更紧凑,谢谢!看起来像这样:var source = new [] {5,6,7}; source.Intersect(new [] {5,7,6})。Count()== source.Length; – CubanX 2010-09-21 15:17:50

+0

@CubanX:请注意,如果源包含任何重复项,那么即使'source.SetEquals(source)'也会返回false。 – 2010-09-21 15:35:09

+0

@Jon好的一点,我可能不得不在那里抛出一个独特的东西,以确保不会发生。 – CubanX 2010-09-21 21:57:50

9

你可以建立一组,然后使用HashSet<T>.SetEquals。它不是严格在LINQ中,但它可以很好地与它搭配使用:)

当然,您可以轻松编写自己的扩展方法来扩展它。事情是这样的:

public static bool SetEquals<T>(this IEnumerable<T> source, IEnumerable<T> other) 
{ 
    HashSet<T> hashSet = new HashSet<T>(source); 
    return hashSet.SetEquals(other); // Doesn't recurse! Calls HashSet.SetEquals 
} 

编辑:正如在评论中指出,这忽视的元素出现的次数,以及订货 - 所以{ 1, 2 }将是“设置为等于”来{ 1, 2, 1, 2, 1, 1, 1 }。如果这不是你想要的,它会变得更复杂一点。

+0

所以1,2会“等于”1,1,1,2,2,2? – spender 2010-09-21 13:39:42

+0

@spender:对于*设置*相等,这是正确的。每个集合中的元素集是相同的。值得强调的是 - 将被编辑。 – 2010-09-21 13:40:51

+0

乔恩,有时在这样的方法中,我不能决定是否将它写入,或者像'HashSet hashSet = source那样做HashSet ??新的HashSet (来源);'*可能*节省构建新的'HashSet '的成本。你对此有何看法? – 2010-09-21 13:43:53

2

我就是这么做的:

public static bool SetEquivalent<T>(
    this IEnumerable<T> aSet, 
    IEnumerable<T> anotherSet) 
{ 
    var diffA = aSet.Except(anotherSet).Count(); 
    var diffB = anotherSet.Except(aSet).Count(); 
    return diffA == diffB && diffA == 0; 
} 
相关问题