2012-02-15 34 views
7

Xin lỗi để đăng các câu hỏi cơ bản như vậy, tôi mới vào LINQ và đang cố gắng tìm ra cách tốt nhất để thực hiện việc này lặp qua từng IList.Xóa các mục trong một IList <> từ một IList khác <>

Tôi có 2 ILists<> với các đối tượng tùy chỉnh. Tôi muốn xóa tất cả các mục phù hợp khỏi danh sách nằm trong danh sách khác.

IList<ItemDTO> list1 = itemsbl.GetBestItems(); 
IList<ItemDTO> list2 = itemsbl.GetWorstItems(); 

Tôi cần phải xóa tất cả các mục trong list1 từ list2. Tôi đã nhìn vào phương pháp Except() nhưng dường như tôi cần lớp ItemsDTO của mình để ghi đè các phương thức GetHashCodeEquals để làm việc, nhưng tôi gặp khó khăn khi tìm một số ví dụ về điều này.

Có thể ai đó vui lòng chỉ cho tôi cách tốt nhất để xóa list1 từ list2?

Cảm ơn lần nữa

Trả lời

9

Bạn có thể sử dụng phương thức Ngoại lệ để thực hiện việc này.

var newList = list2.Except(list1).ToList(); 

Nếu bạn muốn thay thế List2 sau đó chỉ cần làm điều này:

list2 = list2.Except(list1).ToList(); 

Từ MSDN:

Để so sánh các loại dữ liệu tùy chỉnh, thực hiện các giao diện IEquatable generic và cung cấp riêng của bạn Các phương thức GetHashCode và Equals cho loại . Trình so sánh bình đẳng mặc định, Mặc định, được sử dụng để so sánh các giá trị của các loại thực hiện IEquatable với giá trị .

+0

Cảm ơn bạn, tôi đã kết thúc điều chỉnh lớp học của tôi phù hợp để tôi có thể chúng ta Trừ() ... Cảm ơn bạn tất cả mọi người, tôi chắc chắn rằng tất cả các giải pháp khác là chỉ là tốt ...:) – Nugs

1

Băm chắc chắn là một cách hay, @Jon Skeet bên dưới trả lời cho một câu hỏi tương tự sẽ cung cấp cho bạn giải pháp.

nên về cơ bản cú pháp là:

var setToRemove = new HashSet<ItemDTO>(list1); 
list2.RemoveAll(x => setToRemove.Contains(x)); 

Using LINQ to remove elements from a List<T>

hy vọng điều này sẽ giúp.

+0

Tôi không biết tại sao, nhưng RemoveAll() không phải là một lựa chọn cho tôi ... – Nugs

+3

IList là giao diện mà List implements.IList được sử dụng cho các lớp sưu tập khác. Lớp List chứa các phương thức có thể không được định nghĩa trong IList. Vì vậy, bằng cách gán đối tượng danh sách gốc của bạn cho IList, bạn sẽ không còn có quyền truy cập vào bất kỳ phương thức duy nhất nào của Danh sách. Trừ khi bạn có lý do để sử dụng IList , tôi khuyên bạn nên sử dụng Danh sách . MSDN: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx – Nickz

1
var list1 = new List<string> { "A", "B", "C" }; 
var list2 = new List<string> { "A", "C", "E", "B", "D", "G", "F" }; 
list2.RemoveAll(list1.Contains); 

cũng sẽ hoạt động. Lưu ý rằng list1.Contains thực sự là một lambda

s => list1.Contains(s) 

-A.

+0

Tôi không biết tại sao, nhưng RemoveAll() không phải là một tùy chọn cho tôi ... – Nugs

+0

'list.Contains' không thực sự là một lambda. Mặc dù nó hoạt động giống nhau ở đây. – svick

+1

Tôi đã đề cập rằng bởi vì tôi nghĩ rằng điều quan trọng là RemoveAll mất một vị từ, đặc biệt là vì các đối tượng của OP có thể không có sự bình đẳng/so sánh được thực hiện. – Ani

0

Điều đó có nghĩa là bạn cần thông báo cho thời gian chạy .net cách xác định xem hai phiên bản của một lớp có bằng nhau hay không (ví dụ: cách xác định xem một phiên bản của ItemDTO có bằng một phiên bản khác của ItemDTO) hay không.

để làm điều này, ghi đè Equals

public class ItemDTO 
{ 
    public override bool Equals(object obj) 
    { 
     var otherItem = obj as ItemDTO; 

     if (otherItem == null) 
     { 
      // this will be because either 'obj' is null or it is not of type ItemDTO. 
      return false; 
     } 

     return otherItem.SomeProperty == this.SomeProperty 
       && otherItem.OtherProperty == this.OtherProperty; 
    } 
} 

Nếu bạn không làm điều này, nó sẽ chỉ loại bỏ bất kỳ tài liệu tham khảo trong danh sách mà điểm đến thể hiện vật lý giống như người kia. Sau đó, bạn có thể sử dụng các phương thức Ngoại trừ hoặc RemoveAll hoặc phương pháp khác mà bạn quyết định sử dụng.

Bạn cũng sẽ cần ghi đè GetHashcode, xem liên kết bên dưới để biết thêm thông tin về điều đó.

Xem Guidelines for Overloading Equals and GetHashcode

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