2010-09-21 33 views
6

Tôi biết LINQ có phương thức SequenceEquals. Phương thức này đảm bảo mỗi giá trị mục trong mỗi bộ sưu tập phù hợp, theo cùng thứ tự.Có phương pháp tương đương LINQ không?

Điều tôi đang tìm kiếm là một loại chức năng "Tương đương" hơn. Chỉ cần cả hai dãy chứa cùng một mục, không nhất thiết phải theo thứ tự như nhau. Ví dụ: nUnit có CollectionAssert.AreEqual()CollectionAssert.AreEquivalent() làm những gì tôi đang giải thích.

Tôi biết rằng tôi có thể làm điều này bằng cách:

  1. đặt hàng danh sách trước thời hạn và sử dụng SequenceEquals
  2. Sử dụng Intersect, sau đó nhìn thấy nếu ngã tư bằng với chuỗi gốc.

Ví dụ:

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

Có một sai lầm trong ví dụ của câu trả lời. Bạn cần phải so sánh nó với cả hai tính nếu không thì hàm của bạn sẽ trả về 'true' khi nguồn là một tập con của đích. I E. nguồn {5,6} và mục tiêu {5,7,6} – cellik

Trả lời

8

Tôi sẽ tạo phương thức tiện ích mở rộng giao nhau và sau đó so sánh số lượng.

+0

Bạn nhận được câu trả lời cho cho tôi ý tưởng để so sánh số lượng, vì vậy nó làm cho nó đẹp và nhỏ gọn, cảm ơn! Hình như thế này: var source = new [] {5, 6, 7}; source.Intersect (new [] {5, 7, 6}). Count() == nguồn.Length; – CubanX

+0

@CubanX: Lưu ý rằng nếu nguồn chứa bất kỳ bản sao nào, thì ngay cả 'source.SetEquals (source)' sẽ trả về false. –

+0

@Jon Tốt, tôi có thể phải ném một khác biệt trong đó để đảm bảo rằng sẽ không xảy ra. – CubanX

9

Bạn có thể xây dựng một tập và sau đó sử dụng HashSet<T>.SetEquals. Nó không hoàn toàn nằm trong LINQ, nhưng nó chơi độc đáo với nó :)

Tất nhiên, bạn có thể dễ dàng viết phương pháp mở rộng của riêng bạn để mở rộng này. Một cái gì đó như thế này:

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 
} 

EDIT: Như đã nêu trong các ý kiến, này bỏ qua số lần các yếu tố xảy ra, cũng như thứ tự - vì vậy { 1, 2 } sẽ là "thiết lập bình đẳng" để { 1, 2, 1, 2, 1, 1, 1 }. Nếu đó không phải là điều bạn muốn, nó sẽ phức tạp hơn một chút.

+0

vì vậy 1,2 sẽ "bằng" 1,1,1,2,2,2? – spender

+0

@spender: Đối với * set * bình đẳng, điều đó đúng. Tập hợp các phần tử trong mỗi bộ sưu tập giống nhau. Đó là giá trị nổi bật mặc dù - sẽ chỉnh sửa. –

+0

Jon, đôi khi trong các phương pháp như thế này, tôi không thể quyết định có nên viết nó như bạn có nó hoặc để làm một cái gì đó như 'HashSet hashSet = nguồn như HashSet ?? new HashSet (nguồn); '* có khả năng * tiết kiệm chi phí xây dựng một' HashSet 'mới. Bạn có ý kiến ​​về điều đó không? –

2

tôi đã làm nó theo cách này:

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; 
} 
Các vấn đề liên quan