Bagaimana cara menghapus item dari daftar di C #?

192

Saya memiliki daftar yang disimpan di daftar hasil sebagai berikut:

var resultlist = results.ToList();

Itu terlihat seperti ini:

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

Bagaimana cara menghapus ID 2 dari daftar?

Nate Pet
sumber

Jawaban:

368

List<T> memiliki dua metode yang dapat Anda gunakan.

RemoveAt (int index) dapat digunakan jika Anda mengetahui indeks item tersebut. Sebagai contoh:

resultlist.RemoveAt(1);

Atau Anda dapat menggunakan Hapus (item T) :

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

Ketika Anda tidak yakin item tersebut benar-benar ada, Anda dapat menggunakan SingleOrDefault . SingleOrDefaultakan kembali nulljika tidak ada item ( Singleakan mengeluarkan pengecualian ketika item tidak dapat ditemukan). Keduanya akan melempar ketika ada nilai duplikat (dua item dengan yang sama id).

var itemToRemove = resultlist.SingleOrDefault(r => r.Id == 2);
if (itemToRemove != null)
    resultList.Remove(itemToRemove);
Wouter de Kort
sumber
5
baik, daripada mungkinvar itemsToRemove = resultlist.Where(r => r.Id == 2); foreach (var itemToRemove in ItemsToRemove) resultList.Remove(itemToRemove);
Vlad
1
Bukankah ini seharusnya resultlist.Items.RemoveAt(1);?
DreamTeK
50

Jawaban singkat:
Hapus (dari daftar results)

results.RemoveAll(r => r.ID == 2);akan menghapus item dengan ID 2 di results(di tempat).

Filter (tanpa menghapus dari daftar asli results):

var filtered = result.Where(f => f.ID != 2);mengembalikan semua item kecuali yang memiliki ID 2

Jawaban terinci:

Saya pikir .RemoveAll()ini sangat fleksibel, karena Anda dapat memiliki daftar ID item yang ingin Anda hapus - silakan perhatikan contoh berikut.

Jika Anda memiliki:

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

dan menetapkan beberapa nilai resultssebagai berikut:

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" },
};

Kemudian Anda dapat menentukan daftar ID yang akan dihapus:

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

Dan cukup gunakan ini untuk menghapusnya:

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

Ini akan menghapus item 2 dan 3 dan menyimpan item 1 dan 4 - seperti yang ditentukan oleh removeList. Perhatikan bahwa ini terjadi, jadi tidak ada tugas tambahan yang diperlukan.

Tentu saja, Anda juga dapat menggunakannya pada item tunggal seperti:

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

di mana ia akan menghapus Bill dengan ID 4 dalam contoh kita.


DotNetFiddle: Jalankan demo

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

Ada sedikit pembantu Linq yang saya sukai yang mudah diterapkan dan dapat membuat kueri dengan kondisi "di mana tidak" sedikit lebih mudah dibaca:

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();
KeithS
sumber
1
Pendekatan lain yang serupa (yang menggunakan predikat) adalah dengan menggunakan List.FindIndex/ List.RemoteAt(yang memiliki fitur "baik" atau "tidak begitu baik" sebagai operasi yang bermutasi).
Benar, tetapi berhati-hatilah untuk mengatakan bahwa operasi Daftar sedang bermutasi. Daftar menggunakan larik di belakang layar, dan ia dapat membuat ulang lariknya dengan kapasitas yang lebih kecil atau lebih besar ketika dianggap perlu. Biasanya , penghapusan adalah mutasi in-place dari array yang ada.
KeithS
Ini bukan utas aman, dan untuk kesederhanaannya Anda bisa menggunakan SingleOrDefault, itu tidak perlu dimuat dalam metode statis
Tidak ada yang mengatakan itu aman-thread (dan apakah itu tergantung pada apa yang seharusnya dilakukan oleh thread; mungkin sebenarnya lebih disukai untuk memberikan konstruksi memori yang berbeda dengan thread pekerja dibandingkan membiarkan mereka semua bekerja pada satu koleksi bersamaan). ), dan OP menginginkan semua catatan kecuali yang cocok dengan predikat, jadi SingleOrDefault akan mengembalikan apa yang sebenarnya tidak mereka inginkan. "Metode statis" sebenarnya merupakan metode ekstensi, seperti kebanyakan Linq, dan bekerja kapan pun Anda tidak menginginkannya (satu elemen atau banyak) lebih mudah untuk didefinisikan daripada apa yang Anda lakukan.
KeithS
5

Ada pendekatan lain. Ini menggunakan List.FindIndexdan List.RemoveAt.

Walaupun saya mungkin akan menggunakan solusi yang disajikan oleh KeithS (hanya yang sederhana Where/ ToList) pendekatan ini berbeda karena ia bermutasi objek daftar asli. Ini bisa menjadi "fitur" yang baik (atau buruk) tergantung pada harapan.

Dalam kasus apapun, FindIndex(ditambah dengan penjaga) memastikan RemoveAtakan benar jika ada kesenjangan dalam ID atau memesan salah, dll, dan menggunakan RemoveAt(vs Remove) menghindari suatu kedua O (n) mencari melalui daftar.

Berikut ini cuplikan 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

Selamat coding.


sumber
4

Anda tidak menentukan daftar jenis apa, tetapi Daftar generik dapat menggunakan RemoveAt(index)metode, atau Remove(obj)metode:

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

// RemoveAt(index)
resultList.RemoveAt(1);
mgnoonan
sumber
4

Lebih disederhanakan:

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

tidak perlu membuat objek var baru.

Javier Andres Caicedo
sumber
0

... atau hanya resultlist.RemoveAt(1)jika Anda tahu persis indeksnya.

Vlad
sumber
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}");
            }

        }

    }
}
Prabhakaran M
sumber