Benar, jadi saya punya enumerable dan ingin mendapatkan nilai yang berbeda dari itu.
Menggunakan System.Linq
, tentu saja ada metode ekstensi yang disebut Distinct
. Dalam kasus sederhana, ini dapat digunakan tanpa parameter, seperti:
var distinctValues = myStringList.Distinct();
Baik dan bagus, tetapi jika saya memiliki banyak objek yang harus saya tentukan persamaannya, satu-satunya kelebihan yang tersedia adalah:
var distinctValues = myCustomerList.Distinct(someEqualityComparer);
Argumen pembanding kesetaraan harus merupakan turunan dari IEqualityComparer<T>
. Saya bisa melakukan ini, tentu saja, tetapi agak bertele-tele dan, yah, tidak jelas.
Apa yang saya harapkan adalah kelebihan yang akan mengambil lambda, katakanlah Func <T, T, bool>:
var distinctValues
= myCustomerList.Distinct((c1, c2) => c1.CustomerId == c2.CustomerId);
Adakah yang tahu jika ada ekstensi seperti itu, atau beberapa solusi yang setara? Atau apakah saya melewatkan sesuatu?
Atau, apakah ada cara untuk menentukan inline IEqualityComparer (mempermalukan saya)?
Memperbarui
Saya menemukan balasan oleh Anders Hejlsberg ke sebuah posting di forum MSDN tentang hal ini. Dia berkata:
Masalah yang akan Anda hadapi adalah ketika dua objek membandingkan sama, mereka harus memiliki nilai balik GetHashCode yang sama (atau tabel hash yang digunakan secara internal oleh Distinct tidak akan berfungsi dengan benar). Kami menggunakan IEqualityComparer karena ini mengemas implementasi Equals dan GetHashCode yang kompatibel ke dalam satu antarmuka.
Saya kira itu masuk akal ..
sumber
.Distinct(new KeyEqualityComparer<Customer,string>(c1 => c1.CustomerId))
, dan menjelaskan mengapa GetHashCode () penting untuk bekerja dengan baik.Jawaban:
sumber
DistinctBy
(atau bahkanDistinct
, karena tanda tangannya akan unik).yield
pernyataan tersebut sehingga streaming tidak dimungkinkan secara teknis. Terima kasih atas jawaban Anda. Saya akan menggunakannya ketika coding di C #. ;-)Sepertinya saya inginkan
DistinctBy
dari MoreLINQ . Anda kemudian dapat menulis:Berikut adalah versi cut-down dari
DistinctBy
(tidak ada nullity memeriksa dan tidak ada opsi untuk menentukan pembanding kunci Anda sendiri):sumber
yield
+ lib ekstra, foreach dapat ditulis ulang sebagaireturn source.Where(element => knownKeys.Add(keySelector(element)));
Membungkus semuanya . Saya pikir sebagian besar orang yang datang ke sini seperti saya menginginkan solusi sesederhana mungkin tanpa menggunakan perpustakaan dan dengan kinerja terbaik .
(Grup yang diterima dengan metode untuk saya, saya pikir adalah berlebihan dalam hal kinerja.)
Berikut ini adalah metode ekstensi sederhana menggunakan antarmuka IEqualityComparer yang juga berfungsi untuk nilai null.
Pemakaian:
Kode Metode Perpanjangan
sumber
Tidak, tidak ada metode ekstensi yang berlebihan untuk ini. Saya merasa frustrasi di masa lalu dan karena itu saya biasanya menulis kelas pembantu untuk mengatasi masalah ini. Tujuannya adalah untuk mengkonversi
Func<T,T,bool>
keIEqualityComparer<T,T>
.Contoh
Ini memungkinkan Anda untuk menulis yang berikut ini
sumber
IEqualityComparer<T>
dari proyeksi: stackoverflow.com/questions/188120/...Solusi singkat
sumber
Ini akan melakukan apa yang Anda inginkan tetapi saya tidak tahu tentang kinerja:
Setidaknya itu tidak bertele-tele.
sumber
Inilah metode ekstensi sederhana yang melakukan apa yang saya butuhkan ...
Sayang mereka tidak memanggang metode yang berbeda seperti ini ke dalam kerangka kerja, tapi hei ho.
sumber
x.Key
kex.First()
dan mengubah nilai kembali keIEnumerable<T>
Sesuatu yang saya gunakan yang bekerja dengan baik untuk saya.
sumber
Semua solusi yang saya lihat di sini bergantung pada pemilihan bidang yang sudah dapat dibandingkan. Jika seseorang perlu membandingkan dengan cara yang berbeda, solusi ini tampaknya berfungsi secara umum, untuk sesuatu seperti:
sumber
Ambil jalan lain:
Urutan mengembalikan elemen berbeda membandingkannya dengan properti '_myCaustomerProperty'.
sumber
Anda dapat menggunakan InlineComparer
Sampel penggunaan :
Sumber: https://stackoverflow.com/a/5969691/206730
Menggunakan IEqualityComparer untuk Union
Bisakah saya menentukan inline komparator tipe eksplisit saya?
sumber
Anda dapat menggunakan LambdaEqualityComparer:
sumber
Cara rumit untuk melakukan ini adalah menggunakan
Aggregate()
ekstensi, menggunakan kamus sebagai akumulator dengan nilai properti-kunci sebagai kunci:Dan solusi gaya GroupBy menggunakan
ToLookup()
:sumber
Dictionary<int, Customer>
saja?Saya berasumsi Anda memiliki IEnumerable, dan dalam delegasi contoh Anda, Anda ingin c1 dan c2 merujuk pada dua elemen dalam daftar ini?
Saya yakin Anda bisa mencapainya dengan bergabung sendiri var differResults = dari c1 di myList, gabung di c2 di myList on
sumber
Jika
Distinct()
tidak menghasilkan hasil yang unik, coba yang ini:sumber
Paket Microsoft System.Interactive memiliki versi Perbedaan yang mengambil lambda pemilih kunci. Ini secara efektif sama dengan solusi Jon Skeet, tetapi mungkin bermanfaat bagi orang untuk mengetahuinya, dan untuk memeriksa perpustakaan lainnya.
sumber
Inilah cara Anda dapat melakukannya:
Metode ini memungkinkan Anda untuk menggunakannya dengan menentukan satu parameter seperti
.MyDistinct(d => d.Name)
, tetapi juga memungkinkan Anda menentukan kondisi memiliki sebagai parameter kedua seperti:NB Ini juga akan memungkinkan Anda untuk menentukan fungsi lain seperti misalnya
.LastOrDefault(...)
juga.Jika Anda ingin mengekspos kondisi ini, Anda dapat membuatnya lebih sederhana dengan menerapkannya sebagai:
Dalam hal ini, kueri akan terlihat seperti:
NB Di sini, ekspresinya lebih sederhana, tetapi note
.MyDistinct2
menggunakan.FirstOrDefault(...)
secara implisit.Catatan: Contoh di atas menggunakan kelas demo berikut
sumber
IEnumerable
ekstensi lambda:Pemakaian:
sumber