Saya mencari cara yang sangat cepat untuk memfilter koleksi di C #. Saat ini saya menggunakan koleksi <object> Daftar generik, tetapi saya terbuka untuk menggunakan struktur lain jika kinerjanya lebih baik.
Saat ini, saya hanya membuat Daftar baru <object> dan mengulang melalui daftar asli. Jika kriteria penyaringan cocok, saya memasukkan salinan ke daftar baru.
Apakah ada cara yang lebih baik untuk melakukan ini? Apakah ada cara untuk memfilter di tempat sehingga tidak ada daftar sementara yang diperlukan?
c#
collections
filtering
Jason Z
sumber
sumber
Jawaban:
Jika Anda menggunakan C # 3.0 Anda dapat menggunakan linq, jauh lebih baik dan lebih elegan:
Jika Anda tidak dapat menemukan
.Where
, itu berarti Anda perlu mengimporusing System.Linq;
di bagian atas file Anda.sumber
.Where(predefinedQuery)
alih-alih menggunakan.Where(x => x > 7)
?public bool predefinedQuery(int x) { return x > 7; }
. Maka Anda.Where(predefinedQuery)
akan bekerja dengan baik.Berikut ini adalah blok kode / contoh dari beberapa pemfilteran daftar menggunakan tiga metode berbeda yang saya kumpulkan untuk menunjukkan pemfilteran daftar berdasarkan Lambdas dan LINQ.
sumber
List<T>
memilikiFindAll
metode yang akan melakukan penyaringan untuk Anda dan mengembalikan subset dari daftar.MSDN memiliki contoh kode yang bagus di sini: http://msdn.microsoft.com/en-us/library/aa701359(VS.80).aspx
EDIT: Saya menulis ini sebelum saya memiliki pemahaman yang baik tentang LINQ dan
Where()
metodenya. Jika saya menulis ini hari ini saya mungkin akan menggunakan metode yang disebutkan Jorge di atas. TheFindAll
Metode masih bekerja jika Anda terjebak di NET 2.0 lingkungan sekalipun.sumber
Anda dapat menggunakan IEnumerable untuk menghilangkan kebutuhan daftar temp.
di mana Cocok adalah nama metode filter Anda. Dan Anda dapat menggunakan ini seperti:
Ini akan memanggil fungsi GetFilteredItems bila diperlukan dan dalam beberapa kasus Anda tidak menggunakan semua item dalam koleksi yang difilter, ini mungkin memberikan beberapa peningkatan kinerja yang baik.
sumber
Untuk melakukannya di tempat, Anda dapat menggunakan metode RemoveAll dari kelas "Daftar <>" bersama dengan kelas "Predikat" khusus ... tetapi semua yang dilakukan adalah membersihkan kode ... di bawah tenda itu melakukan hal yang sama hal Anda ... tapi ya, itu di tempat, sehingga Anda melakukan hal yang sama daftar temp.
sumber
Anda dapat menggunakan metode FindAll dari Daftar, menyediakan delegasi untuk difilter. Padahal, saya setuju dengan @ IainMH bahwa tidak perlu terlalu mengkhawatirkan diri sendiri kecuali daftar yang besar.
sumber
Atau, jika Anda mau, gunakan sintaks kueri khusus yang disediakan oleh kompiler C # 3:
sumber
Menggunakan LINQ relatif jauh lebih lambat daripada menggunakan predikat yang disediakan untuk
FindAll
metode daftar . Juga berhati-hatilah dengan LINQ karena penghitunganlist
tidak benar-benar dieksekusi sampai Anda mengakses hasilnya. Ini dapat berarti bahwa, ketika Anda merasa telah membuat daftar yang difilter, kontennya mungkin berbeda dengan yang Anda harapkan ketika Anda benar-benar membacanya.sumber
Jika daftar Anda sangat besar dan Anda memfilter berulang kali - Anda dapat mengurutkan daftar asli pada atribut filter, pencarian biner untuk menemukan titik awal dan akhir.
Waktu awal O (n * log (n)) kemudian O (log (n)).
Penyaringan standar akan mengambil O (n) setiap kali.
sumber