2010-09-21 73 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; 
} 
相關問題