Làm cách nào để xóa mục khỏi danh sách trong C #?


189

Tôi có một danh sách được lưu trong danh sách kết quả như sau:

var resultlist = results.ToList();

Nó trông giống như thế này:

ID FirstName  LastName
-- ---------  --------
1  Bill       Smith
2  John       Wilson
3  Doug       Berg

Làm cách nào để xóa ID 2 khỏi danh sách?

Câu trả lời:


364

List<T> có hai phương pháp bạn có thể sử dụng.

RemoveAt (int index) có thể được sử dụng nếu bạn biết chỉ mục của mục. Ví dụ:

resultlist.RemoveAt(1);

Hoặc bạn có thể sử dụng Xóa (mục T) :

var itemToRemove = resultlist.Single(r => r.Id == 2);
resultList.Remove(itemToRemove);

Khi bạn không chắc chắn mục đó thực sự tồn tại, bạn có thể sử dụng SingleOrDefault . SingleOrDefaultsẽ trả lại nullnếu không có mục nào ( Singlesẽ ném ngoại lệ khi không thể tìm thấy mục đó). Cả hai sẽ ném khi có một giá trị trùng lặp (hai mục có cùng id).

var itemToRemove = resultlist.SingleOrDefault(r => r.Id == 2);
if (itemToRemove != null)
    resultList.Remove(itemToRemove);

5
tốt, có lẽvar itemsToRemove = resultlist.Where(r => r.Id == 2); foreach (var itemToRemove in ItemsToRemove) resultList.Remove(itemToRemove);
Vlad

1
Điều này có nên không resultlist.Items.RemoveAt(1);?
DreamTeK

48

Câu trả lời ngắn:
Xóa (khỏi danh sách results)

results.RemoveAll(r => r.ID == 2);sẽ xóa mục có ID 2 tại chỗ results(tại chỗ).

Bộ lọc (không xóa khỏi danh sách gốc results):

var filtered = result.Where(f => f.ID != 2);trả về tất cả các mục ngoại trừ mục có ID 2

Câu trả lời chi tiết:

Tôi nghĩ .RemoveAll()là rất linh hoạt, bởi vì bạn có thể có một danh sách ID vật phẩm mà bạn muốn xóa - vui lòng xem ví dụ sau.

Nếu bạn có:

class myClass {
    public int ID; public string FirstName; public string LastName;
}

và gán một số giá trị resultsnhư sau:

var results=new List<myClass> {
    new myClass()  { ID=1, FirstName="Bill", LastName="Smith" },
    new myClass()  { ID=2, FirstName="John", LastName="Wilson" },
    new myClass()  { ID=3, FirstName="Doug", LastName="Berg" },
    new myClass()  { ID=4, FirstName="Bill", LastName="Wilson" },
};

Sau đó, bạn có thể xác định danh sách ID cần xóa:

var removeList = new List<int>() { 2, 3 };

Và chỉ cần sử dụng điều này để loại bỏ chúng:

results.RemoveAll(r => removeList.Any(a => a==r.ID));

Nó sẽ xóa các mục 2 và 3 và giữ các mục 1 và 4 - theo quy định củaremoveList . Lưu ý rằng điều này xảy ra tại chỗ, do đó không có yêu cầu bổ sung.

Tất nhiên, bạn cũng có thể sử dụng nó trên các mục đơn lẻ như:

results.RemoveAll(r => r.ID==4);

nơi nó sẽ loại bỏ Bill với ID 4 trong ví dụ của chúng tôi.


DotNetFiddle: Chạy bản demo


45
resultList = results.Where(x=>x.Id != 2).ToList();

Có một trình trợ giúp Linq nhỏ mà tôi thích dễ thực hiện và có thể thực hiện các truy vấn với điều kiện "không phải" dễ đọc hơn một chút:

public static IEnumerable<T> ExceptWhere<T>(this IEnumerable<T> source, Predicate<T> predicate)
{
    return source.Where(x=>!predicate(x));
}

//usage in above situation
resultList = results.ExceptWhere(x=>x.Id == 2).ToList();

1
Một cách tiếp cận tương tự khác (sử dụng một vị ngữ) là sử dụng List.FindIndex/ List.RemoteAt(có tính năng "đẹp" hoặc "không đẹp" như là một hoạt động đột biến).

Đúng, nhưng hãy cẩn thận khi nói rằng hoạt động của List đang biến đổi. Danh sách sử dụng một mảng phía sau hậu trường và nó có thể tạo lại mảng của nó với công suất nhỏ hơn hoặc lớn hơn khi nghĩ rằng điều đó là cần thiết. Thông thường , loại bỏ là một đột biến tại chỗ của mảng hiện có.
KeithS

Đây không phải là luồng an toàn và vì đơn giản, bạn chỉ cần sử dụng SingleOrDefault, nó không cần phải được chứa trong một phương thức tĩnh

Không ai nói nó an toàn cho luồng (và liệu nó có phụ thuộc vào những gì các luồng được cho là đang thực hiện hay không, trên thực tế có thể nên đưa ra một cấu trúc trong bộ nhớ khác cho một luồng công nhân thay vì để tất cả chúng hoạt động trên một bộ sưu tập đồng thời ) và OP muốn tất cả các bản ghi ngoại trừ bản ghi khớp với vị từ, do đó, SingleOrDefault thực tế sẽ trả về chính xác những gì họ không muốn. "Phương thức tĩnh" trên thực tế là một phương thức mở rộng, giống như hầu hết Linq và nó hoạt động bất cứ khi nào những gì bạn không muốn (một yếu tố hoặc nhiều yếu tố) dễ xác định hơn những gì bạn làm.
KeithS

5

Có một cách tiếp cận khác. Nó sử dụng List.FindIndexList.RemoveAt.

Trong khi tôi có thể sẽ sử dụng giải pháp được trình bày bởi KeithS (chỉ đơn giản Where/ ToList) cách tiếp cận này khác ở chỗ nó biến đổi đối tượng danh sách ban đầu. Đây có thể là một "tính năng" tốt (hoặc xấu) tùy theo mong đợi.

Trong mọi trường hợp, FindIndex(kết hợp với một người bảo vệ) đảm bảo RemoveAtsẽ đúng nếu có các khoảng trống trong ID hoặc thứ tự sai, v.v. và sử dụng RemoveAt(vs Remove) để tránh một giây tìm kiếm O (n) trong danh sách.

Đây là đoạn mã LINQPad :

var list = new List<int> { 1, 3, 2 };
var index = list.FindIndex(i => i == 2); // like Where/Single
if (index >= 0) {   // ensure item found
    list.RemoveAt(index);
}
list.Dump();        // results -> 1, 3

Chúc mừng mã hóa.


4

Bạn không chỉ định loại danh sách nào, nhưng Danh sách chung có thể sử dụng RemoveAt(index)phương thức hoặc Remove(obj)phương thức:

// Remove(obj)
var item = resultList.Single(x => x.Id == 2);
resultList.Remove(item);

// RemoveAt(index)
resultList.RemoveAt(1);

4

Đơn giản hơn:

resultList.Remove(resultList.Single(x => x.Id == 2));

không cần phải tạo một đối tượng var mới.


0

... Hoặc chỉ resultlist.RemoveAt(1)khi bạn biết chính xác chỉ số.


0
{
    class Program
    {
        public static List<Product> list;
        static void Main(string[] args)
        {

            list = new List<Product>() { new Product() { ProductId=1, Name="Nike 12N0",Brand="Nike",Price=12000,Quantity=50},
                 new Product() { ProductId =2, Name = "Puma 560K", Brand = "Puma", Price = 120000, Quantity = 55 },
                 new Product() { ProductId=3, Name="WoodLand V2",Brand="WoodLand",Price=21020,Quantity=25},
                 new Product() { ProductId=4, Name="Adidas S52",Brand="Adidas",Price=20000,Quantity=35},
                 new Product() { ProductId=5, Name="Rebook SPEED2O",Brand="Rebook",Price=1200,Quantity=15}};


            Console.WriteLine("Enter ProductID to remove");
            int uno = Convert.ToInt32(Console.ReadLine());
            var itemToRemove = list.Find(r => r.ProductId == uno);
            if (itemToRemove != null)
                list.Remove(itemToRemove);
            Console.WriteLine($"{itemToRemove.ProductId}{itemToRemove.Name}{itemToRemove.Brand}{itemToRemove.Price}{ itemToRemove.Quantity}");
            Console.WriteLine("------------sucessfully Removed---------------");

            var query2 = from x in list select x;
            foreach (var item in query2)
            {
                /*Console.WriteLine(item.ProductId+" "+item.Name+" "+item.Brand+" "+item.Price+" "+item.Quantity );*/
                Console.WriteLine($"{item.ProductId}{item.Name}{item.Brand}{item.Price}{ item.Quantity}");
            }

        }

    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.