2011-12-16 15 views
7

Tôi có một danh sách các đối tượng mà một số người trong số họ có cùng một Id, vì vậy tôi muốn loại bỏ những yếu tố đó được nhân đôi.Riêng biệt trong khuôn khổ pháp nhân

Tôi đã thử với một cái gì đó như thế này:

List<post> posts = postsFromDatabase.Distinct().ToList(); 

Nhưng nó không hoạt động!

Vì vậy, tôi đã viết phương pháp này để tránh các bản sao:

public List<Post> PostWithOutDuplicates(List<Post> posts) 
    { 
     List<Post> postWithOutInclude = new List<Post>(); 
     var noDupes = posts.Select(x => x.Id).Distinct(); 
     if (noDupes.Count() < posts.Count) 
     { 
      foreach (int idPost in noDupes) 
      { 
       postWithOutInclude.Add(posts.Where(x => x.Id == idPost).First()); 
      } 
      return postWithOutInclude; 
     } 
     else 
     { 
      return posts; 
     } 
    } 

Bất kỳ ý tưởng làm thế nào để cải thiện hiệu suất ??

Thanx trước.

+0

Làm thế nào để bạn có ID trùng lặp? Điều đó có vẻ như một vấn đề lớn hơn để giải quyết. – Mikeb

Trả lời

25

Đây là thoải mái và dễ dàng:

List<Post> posts = posts 
.GroupBy(x => x.Id) 
.Select(x => x.FirstOrDefault()) 

Nhưng nếu bạn muốn viết nó một cách đúng đắn, tôi muốn khuyên bạn nên viết nó như thế này:

public class PostComparer : IEqualityComparer<Post> 
{ 
    #region IEqualityComparer<Post> Members 

    public bool Equals(Post x, Post y) 
    { 
     return x.Id.Equals(y.Id); 
    } 

    public int GetHashCode(Post obj) 
    { 
     return obj.Id.GetHashCode(); 
    } 

    #endregion 
} 

Vì nó sẽ cung cấp cho bạn tự do hơn khi nói đến các so sánh bổ sung. đã viết lớp này, bạn có thể sử dụng nó như sau:

List<Post> posts = postsFromDatabase.Distinct(new PostComparer()).ToList(); 
+2

Tôi nghĩ rằng trong 'GetHashCode' bạn phải sử dụng' obj.Id.GetHashCode() 'vì hashcode phải giống nhau cho hai đối tượng bằng nhau theo phương thức' Equals' (ít nhất MSDN nói điều này). – Slauma

+0

Cũng được phát hiện! Nên có Id.GetHashCode(), bạn nói đúng. Nếu ai đó quan tâm: http://msdn.microsoft.com/en-us/library/ms132151.aspx –

+3

Điều này sẽ xử lý điều này khi dữ liệu trong bộ nhớ. Không tốt. Sử dụng GroupBy-approch: http://stackoverflow.com/questions/8560884/how-to-implement-iequalitycomparer-to-return-distinct-values ​​ –

1

thay vì .First(), hãy thử .FirstOrDefault()

5

Tôi nghĩ rằng viết comparer tùy chỉnh của riêng bạn là một cách tiếp cận tốt.

Dưới đây là một bài viết trong MSDN giải thích chủ đề này rất tốt: http://support.microsoft.com/kb/320727

Lý do mà các biệt không làm việc của mình rằng biệt() không có ý tưởng về làm thế nào để tự xác định được nếu có bằng, do đó, nó sử dụng tham chiếu để xác định nó là cùng một "đối tượng". Nó hoạt động giống như nó được làm việc. Tất cả các lớp trong truy vấn không phải là cùng một đối tượng.

Bằng cách viết trình so sánh của riêng bạn (thật dễ dàng), bạn có thể nói với Distinct() cách so sánh để xác định xem chúng có bằng không.

Chỉnh sửa: Nếu không sử dụng Riêng biệt không phải là vấn đề và tình huống không phải là frecuent, câu trả lời đầu tiên của Piotr Justyna thật đơn giản và hiệu quả.

+0

Tôi khuyên bạn nên sử dụng GroupBy() nếu có thể. –