2009-11-05 36 views
11

Tôi có 2 Danh sách riêng biệt và tôi cần so sánh hai danh sách đó và nhận mọi thứ nhưng giao điểm của hai danh sách. Làm thế nào tôi có thể làm điều này (C#)?Lấy sự khác biệt đối xứng từ danh sách chung

+0

bạn đã thử những gì? – fretje

+0

bạn có ý gì bởi mọi thứ trừ công đoàn? –

+0

Mọi thứ nhưng công đoàn luôn không có gì. Bạn có nghĩa là tất cả mọi thứ ngoại trừ giao lộ? –

Trả lời

13

Bạn có thể sử dụng Except để nhận mọi thứ trừ giao lộ trong hai danh sách.

var differences = listA.Except(listB).Union(listB.Except(listA)); 

Nếu bạn muốn để có được tất cả mọi thứ nhưng đoàn:

var allButUnion = new List<MyClass>(); 

(Các công đoàn là tất cả mọi thứ trong cả hai danh sách - tất cả mọi thứ nhưng công đoàn là tập rỗng ...)

+1

Cho rằng bạn đang sử dụng từ "giao lộ" để mô tả ý nghĩa của nó bằng tiếng Anh, không có ý nghĩa để sử dụng nó trong mã?:) –

+0

hehehe, true :) –

+0

Mặc dù, tôi có vẻ nhớ, khi tôi phải làm điều này cho một cái gì đó, điều này có hiệu quả hơn một chút so với tổng số công đoàn và loại bỏ giao lộ ... –

6

Bạn có nghĩa là mọi thứ chỉ có trong một danh sách hoặc mục khác? Làm thế nào về:

var allButIntersection = a.Union(b).Except(a.Intersect(b)); 

Đó có thể là một chút không hiệu quả, nhưng nó khá đơn giản cho biết ý bạn là gì (giả sử tôi đã phiên dịch bạn một cách chính xác).

0

Sử dụng Trừ:

List<int> l1 = new List<int>(new[] { 1, 2, 3, 4 }); 
List<int> l2 = new List<int>(new[] { 2, 4 }); 
var l3 = l1.Except(l2); 
+1

Điều đó không chỉ trả lại các mục trong l1 không có trong l2? Điều gì sẽ xảy ra nếu có các mục trong l2 không có trong l1? –

34

Nếu bạn có nghĩa là tập hợp của tất cả mọi thứ nhưng ngã tư (chênh lệch đối xứng), bạn có thể thử:

var set = new HashSet<Type>(list1); 
set.SymmetricExceptWith(list2); 
+2

Tuyệt vời - có vẻ như cách tốt nhất để làm điều đó với tôi. –

+2

Rất đẹp! Đó là sạch hơn nhiều so với những gì tôi đã có. –

0
var theUnion = list1.Concat(list2); 
var theIntersection = list1.Intersect(list2); 
var theSymmetricDifference = theUnion.Except(theIntersection); 
1

Something như thế này?

String[] one = new String[] { "Merry", "Metal", "Median", "Medium", "Malfunction", "Mean", "Measure", "Melt", "Merit", "Metaphysical", "Mental", "Menial", "Mend", "Find" }; 
      String[] two = new String[] { "Merry", "Metal", "Find", "Puncture", "Revise", "Clamp", "Menial" }; 

List<String> tmp = one.Except(two).ToList(); 
tmp.AddRange(two.Except(one)); 

String[] result = tmp.ToArray(); 
1

Đây là phương pháp mở rộng chung. Rosetta Code sử dụng Concat, và Djeefther Souza nói nó hiệu quả hơn.

public static class LINQSetExtensions 
{ 
    // Made aware of the name for this from Swift 
    // https://stackoverflow.com/questions/1683147/get-the-symmetric-difference-from-generic-lists 
    // Generic implementation adapted from https://www.rosettacode.org/wiki/Symmetric_difference 
    public static IEnumerable<T> SymmetricDifference<T>(this IEnumerable<T> first, IEnumerable<T> second) 
    { 
     // I've used Union in the past, but I suppose Concat works. 
     // No idea if they perform differently. 
     return first.Except(second).Concat(second.Except(first)); 
    } 
} 

Tôi chưa thực sự đánh giá nó. Tôi nghĩ rằng nó sẽ phụ thuộc vào cách Union và Concat được thực hiện. Trong thế giới mơ ước của tôi, .NET sử dụng một thuật toán khác nhau tùy thuộc vào loại dữ liệu hoặc kích thước thiết lập, mặc dù cho IEnumerable nó không thể xác định kích thước thiết lập trước.

Ngoài ra, bạn có thể bỏ qua khá nhiều câu trả lời của tôi - Jon Skeet nói rằng phương pháp HashSet "Tuyệt vời - trông giống như cách tốt nhất để làm điều đó với tôi."

Các vấn đề liên quan