2010-04-30 27 views
126

Tôi đang cố gắng tìm ra cách duyệt qua danh sách các mục chung mà tôi muốn xóa khỏi danh sách các mục khác.Xóa các mục khỏi một danh sách trong một số khác

Vì vậy, chúng ta hãy nói rằng tôi có điều này là một ví dụ giả

List<car> list1 = GetTheList(); 
List<car> list2 = GetSomeOtherList(); 

Tôi muốn đi qua list1 với một foreach và loại bỏ từng mục trong List1 mà cũng được chứa trong List2.

Tôi không chắc chắn cách thực hiện điều đó vì foreach không dựa trên chỉ mục.

+1

Bạn muốn loại bỏ các mục trong List1 mà cũng trong List2? –

+0

Bạn cần phải xóa các mục khỏi danh sách1 và thêm chúng vào list2 hoặc cái gì khác? – danish

+0

Liên quan: http://stackoverflow.com/questions/2477633/a-question-about-comparing-listt –

Trả lời

246

Bạn có thể sử dụng Except:

List<car> list1 = GetTheList(); 
List<car> list2 = GetSomeOtherList(); 
List<car> result = list2.Except(list1).ToList(); 

Bạn có thể thậm chí không cần các biến tạm thời:

List<car> result = GetSomeOtherList().Except(GetTheList()).ToList(); 

Lưu ý rằng Except không thay đổi một trong hai danh sách - nó tạo ra một mới danh sách với kết quả.

+8

Điểm nhỏ, nhưng điều này sẽ tạo ra một 'IEnumerable ', không phải là một' Danh sách '. Bạn cần phải gọi 'ToList()' để lấy lại danh sách. Ngoài ra, tôi tin rằng nó nên được 'GetSomeOtherList(). Ngoại trừ (GetTheList()). ToList()' –

+5

Bạn cũng sẽ cần 'using System.Linq;' nếu bạn không có nó trước đây. – yellavon

+0

Tôi đã thêm bằng System.Linq nhưng tôi vẫn không thể truy cập Ngoại trừ. Nhưng trong trường hợp của tôi, tôi đang sử dụng ArrayList. Bất kỳ ý tưởng về cách làm cho nó làm việc với ArrayList? – BKSpurgeon

23

Bạn không cần chỉ mục vì lớp List<T> cho phép bạn xóa các mục theo giá trị thay vì chỉ mục bằng cách sử dụng hàm Remove.

foreach(car item in list1) list2.Remove(item); 
+1

+1, nhưng IMO bạn nên sử dụng các dấu ngoặc xung quanh câu lệnh 'list2.Remove (item);'. – ANeves

+2

@sr pt: Tôi luôn sử dụng các dấu ngoặc trên các câu lệnh xuất hiện trên một dòng khác, nhưng không phải trên các khối lệnh đơn mà tôi có thể/làm trên cùng một dòng với câu lệnh điều khiển luồng. –

+0

Miễn là bạn nhất quán, không quan trọng nếu bạn sử dụng dấu ngoặc đơn hay không .. IMO :) –

21

Tôi khuyên bạn nên sử dụng LINQ extension methods. Bạn có thể dễ dàng làm điều đó với một dòng mã như vậy:

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

Đây là giả định tất nhiên các đối tượng trong danh sách1 mà bạn đang xóa khỏi danh sách 2 là cùng một trường hợp.

+1

Nó cũng loại bỏ các bản sao. –

-4

Đây ya đi ..

List<string> list = new List<string>() { "1", "2", "3" }; 
    List<string> remove = new List<string>() { "2" }; 

    list.ForEach(s => 
     { 
      if (remove.Contains(s)) 
      { 
       list.Remove(s); 
      } 
     }); 
+3

-1. Điều này sẽ ném một ngoại lệ sau khi mục đầu tiên bị xóa. Ngoài ra, đó là (nói chung) một ý tưởng tốt hơn để đi qua danh sách để * loại bỏ *, vì nó thường nhỏ hơn. Bạn cũng đang buộc nhiều danh sách traversals làm theo cách này. –

10

Bạn có thể sử dụng LINQ, nhưng tôi sẽ đi với RemoveAll phương pháp. Tôi nghĩ đó là cách thể hiện ý định của bạn tốt hơn.

var integers = new List<int> { 1, 2, 3, 4, 5 }; 

var remove = new List<int> { 1, 3, 5 }; 

integers.RemoveAll(i => remove.Contains(i)); 
+7

Hoặc thậm chí đơn giản hơn với các nhóm phương pháp bạn có thể làm - số nguyên.RemoveAll (remove.Contains); – Ryan

4

Giải pháp 1: Bạn có thể làm như thế này:

List<car> result = GetSomeOtherList().Except(GetTheList()).ToList(); 

Nhưng trong một số trường hợp có thể giải pháp này không làm việc. nếu nó không hoạt động, bạn có thể sử dụng giải pháp thứ hai của tôi.

Giải pháp 2:

List<car> list1 = GetTheList(); 
List<car> list2 = GetSomeOtherList(); 

chúng ta giả vờ list1 đó là danh sách chính của bạn và List2 là danh sách secondry của bạn và bạn muốn để có được mặt hàng của list1 mà không mục của List2.

var result = list1.Where(p => !list2.Any(x => x.ID == p.ID && x.property1 == p.property1)).ToList(); 
8

Trong trường hợp của tôi, tôi có hai danh sách khác nhau, với số nhận dạng chung, giống như khóa ngoài. Giải pháp thứ hai được trích dẫn bởi "nzrytmn":

var result = list1.Where(p => !list2.Any(x => x.ID == p.ID && x.property1 == p.property1)).ToList(); 

Là một trong đó phù hợp nhất trong hoàn cảnh của tôi. Tôi cần tải một DropDownList mà không có các bản ghi đã được đăng ký.

Cảm ơn bạn !!!

Đây là mã của tôi:

t1 = new T1(); 
t2 = new T2(); 

List<T1> list1 = t1.getList(); 
List<T2> list2 = t2.getList(); 

ddlT3.DataSource= list2.Where(s => !list1.Any(p => p.Id == s.ID)).ToList(); 
ddlT3.DataTextField = "AnyThing"; 
ddlT3.DataValueField = "IdAnyThing"; 
ddlT3.DataBind(); 
3
list1.RemoveAll(l => list2.Contains(l)); 
+0

a.k.a. "hoàn toàn không tinh khiết" :-) –

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