2010-06-29 43 views
5

Với các dữ liệu saubiểu Lambda để tìm sự khác biệt

string[] data = { "a", "a", "b" }; 

tôi đã rất muốn tìm thấy bản sao và có được kết quả này:

a 

Tôi đã thử các mã sau

var a = data.Distinct().ToList(); 
var b = a.Except(a).ToList(); 

rõ ràng điều này không hoạt động, tôi có thể thấy những gì đang xảy ra ở trên nhưng tôi không chắc chắn làm thế nào để sửa chữa nó.

Trả lời

11

Khi thời gian chạy là không có vấn đề, bạn có thể sử dụng

var duplicates = data.Where(s => data.Count(t => t == s) > 1).Distinct().ToList(); 

Tốt O cũ (n^n) =)

Edit: Bây giờ cho một giải pháp tốt hơn. =) Nếu bạn định nghĩa một phương pháp khuyến nông mới như

static class Extensions 
{   

    public static IEnumerable<T> Duplicates<T>(this IEnumerable<T> input) 
    { 
     HashSet<T> hash = new HashSet<T>(); 
     foreach (T item in input) 
     { 
      if (!hash.Contains(item)) 
      { 
       hash.Add(item); 
      } 
      else 
      { 
       yield return item; 
      } 
     } 
    } 
} 

bạn có thể sử dụng

var duplicates = data.Duplicates().Distinct().ToArray(); 
+0

Giải pháp tốt với bộ băm. Tôi đã suy nghĩ theo những dòng đó, nhưng rõ ràng là chưa thức dậy ... – Noldorin

+0

Giải pháp tốt với bộ băm thực sự! Tôi biết tôi có thể làm theo cách đó, nhưng không biết có thể mở rộng ngôn ngữ như thế được không! – user375049

1

Sắp xếp dữ liệu, lặp lại thông tin và nhớ mục cuối cùng. Khi mục hiện tại giống với mục cuối cùng, mục trùng lặp của nó. Điều này có thể dễ dàng thực hiện hoặc lặp lại hoặc sử dụng một biểu thức lambda trong thời gian O (n * log (n)).

+0

Đây là những gì tôi đang cố gắng làm, nhưng học cách viết lambdas và không rõ ràng cách thực hiện. – user375049

5

Sử dụng nhóm bằng các công cụ, hiệu suất của những phương pháp này khá tốt. Chỉ có mối quan tâm là chi phí bộ nhớ lớn nếu bạn đang làm việc với các tập dữ liệu lớn.

from g in (from x in data group x by x) 
where g.Count() > 1 
select g.Key; 

--hoặc nếu bạn thích phương pháp khuyến nông

data.GroupBy(x => x) 
    .Where(x => x.Count() > 1) 
    .Select(x => x.Key) 

đâu Count() == 1 đó là mục riêng biệt của bạn và nơi Count() > 1 đó là một hoặc nhiều mục trùng lặp.

Kể từ LINQ là loại lười biếng, nếu bạn không muốn phải đánh giá lại tính toán của bạn, bạn có thể làm điều này:

var g = (from x in data group x by x).ToList(); // grouping result 
// duplicates 
from x in g 
where x.Count() > 1 
select x.Key; 
// distinct 
from x in g 
where x.Count() == 1 
select x.Key; 

Khi tạo nhóm một tập hợp các bộ sẽ được tạo ra. Giả sử rằng đó là một tập hợp với O(1) chèn thời gian chạy của nhóm theo cách tiếp cận là O(n). Chi phí phát sinh cho mỗi hoạt động là hơi cao, nhưng nó phải tương đương với hiệu suất gần tuyến tính.

+0

Tôi sẽ bầu bạn nhưng yêu cầu 15 đại diện để làm điều đó (!) Ví dụ tốt :) – user375049

+0

Bạn có thể thay đổi câu trả lời ưa thích nếu muốn. –

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