2011-11-19 43 views
7

Từ previous question Tôi đã hỏi, RemoveAll là cách sạch nhất để xóa khỏi số List<> dựa trên điều kiện. Tò mò để biết cách tốt nhất để xóa khỏi số LinkedList là không có chức năng RemoveAll ở đó.Xóa khỏi một LinkedList

List<ItemClass> itemsToErase = new List<ItemClass>(); 
    foreach(ItemClass itm in DS) 
    { 
      if(itm.ToBeRemoved) 
       itemsToErase .Add(itm); 
    } 
    foreach(ItemClass eraseItem in itemsToErase) 
    { 
      DS.Remove(eraseItem); 
    }      

EDIT: DS là loại LinkedList<ItemClass>

Trả lời

23

Trong khi bạn không thể loại bỏ các nút từ một LinkedList<T> khi lặp lại nó với foreach, bạn có thể tự lặp các LinkedList<T> bằng cách làm theo các Next tài sản của mỗi LinkedListNode<T>. Chỉ cần nhớ nút tiếp theo của nút trước khi tháo nó:

var list = new LinkedList<int>(Enumerable.Range(0, 10)); 
var node = list.First; 
while (node != null) 
{ 
    var next = node.Next; 
    if (node.Value % 2 == 0) 
     list.Remove(node); 
    node = next; 
} 

Phương pháp mở rộng:

public static int RemoveAll<T>(this LinkedList<T> list, Predicate<T> match) 
{ 
    if (list == null) 
    { 
     throw new ArgumentNullException("list"); 
    } 
    if (match == null) 
    { 
     throw new ArgumentNullException("match"); 
    } 
    var count = 0; 
    var node = list.First; 
    while (node != null) 
    { 
     var next = node.Next; 
     if (match(node.Value)) 
     { 
      list.Remove(node); 
      count++; 
     } 
     node = next; 
    } 
    return count; 
} 

Cách sử dụng:

LinkedList<ItemClass> DS = ... 
DS.RemoveAll(itm => itm.ToBeRemoved); 

Xem thêm: Extension Methods (C# Programming Guide)

+0

Và nếu bạn sử dụng điều này ở nhiều nơi, đó là một ứng cử viên tuyệt vời cho một phương pháp mở rộng. – svick

+0

@svick: Ý tưởng hay; đã thêm phương thức mở rộng. – dtb

+0

Tôi mới sử dụng phương pháp mở rộng. Bạn có thể vui lòng làm thế nào để sử dụng phương pháp này mở rộng cụ thể cho trường hợp của tôi. – devnull

0

Cách duy nhất để xóa một mục khỏi System.Collections.Generic.LinkedList<T> là sử dụng một trong các phương pháp Remove(). Tuy nhiên, thao tác này nhanh hơn việc xóa một biểu mẫu mục List<T> (O(1) thay vì O(n)), vì thao tác này có thể được thực hiện cục bộ. Các mục đằng sau mục đã loại bỏ không được di chuyển, chỉ có hai nút trước và sau khi mục đã xóa phải được liên kết với nhau. removed.Previous.Next = removed.Next; removed.Next.Previous = removed.Previous;. Điều này được thực hiện nội bộ, vì thuộc tính PreviousNext là chỉ đọc.

+2

Trong khi 'Remove (LinkedListNode )' thực sự là O (1), 'Remove (T)' là O (n), bởi vì nó phải tìm mục để loại bỏ đầu tiên. – svick