Saya bermain dengan LINQ untuk mempelajarinya, tetapi saya tidak dapat menemukan cara menggunakannya Distinct
ketika saya tidak memiliki daftar sederhana (daftar sederhana bilangan bulat cukup mudah dilakukan, ini bukan pertanyaannya). Bagaimana jika saya ingin menggunakan Distinct pada daftar Object pada satu atau lebih properti objek?
Contoh: Jika suatu objek adalah Person
, dengan Properti Id
. Bagaimana saya bisa mendapatkan semua Orang dan menggunakannya Distinct
dengan properti Id
objek?
Person1: Id=1, Name="Test1"
Person2: Id=1, Name="Test1"
Person3: Id=2, Name="Test2"
Bagaimana saya bisa mendapatkan hanya Person1
dan Person3
? Apakah itu mungkin?
Jika itu tidak mungkin dengan LINQ, apa cara terbaik untuk memiliki daftar Person
tergantung pada beberapa propertinya di .NET 3.5?
GroupBy
lebih mudah. Jika Anda membutuhkannya di lebih dari satu tempat, itu jauh lebih bersih (IMO) untuk merangkum niat.IQueryable<T>
sini, saya tidak melihat bagaimana itu relevan. Saya setuju bahwa ini tidak akan cocok untuk EF dll, tetapi dalam LINQ ke Objects saya pikir itu lebih cocok daripadaGroupBy
. Konteks pertanyaan selalu penting.Sederhana! Anda ingin mengelompokkan mereka dan memilih pemenang dari grup.
Jika Anda ingin mendefinisikan grup pada beberapa properti, berikut caranya:
sumber
Single()
danSingleOrDefault()
setiap lemparan ketika sumber memiliki lebih dari satu item. Dalam operasi ini, kami mengharapkan kemungkinan bahwa setiap kelompok dapat memiliki lebih dari satu item. Dalam hal ini,First()
lebih disukai daripadaFirstOrDefault()
karena setiap grup harus memiliki setidaknya satu anggota .... kecuali jika Anda menggunakan EntityFramework, yang tidak dapat mengetahui bahwa setiap grup memiliki setidaknya satu anggota dan permintaanFirstOrDefault()
.FirstOrDefault()
github.com/dotnet/efcore/issues/12088 Saya di 3.1, dan saya mendapatkan "tidak dapat menerjemahkan" kesalahan.Menggunakan:
Ini
where
membantu Anda menyaring entri (bisa lebih kompleks) dangroupby
danselect
melakukan fungsi yang berbeda.sumber
Anda juga bisa menggunakan sintaks kueri jika Anda ingin semua sintaks seperti LINQ:
sumber
Saya pikir sudah cukup:
sumber
Solusi kelompok pertama dengan bidang Anda kemudian pilih item firstordefault.
sumber
Anda dapat melakukan ini dengan standar
Linq.ToLookup()
. Ini akan membuat kumpulan nilai untuk setiap kunci unik. Cukup pilih item pertama dalam koleksisumber
Kode berikut secara fungsional setara dengan jawaban Jon Skeet .
Diuji pada .NET 4.5, harus berfungsi pada versi LINQ sebelumnya.
Secara kebetulan, lihat versi terbaru Jon Skeet tentang DistinctBy.cs di Google Code .
sumber
Saya telah menulis sebuah artikel yang menjelaskan cara memperluas fungsi Distinct sehingga Anda dapat melakukan hal berikut:
Inilah artikelnya: Memperluas LINQ - Menentukan Properti dalam Fungsi Berbeda
sumber
Secara pribadi saya menggunakan kelas berikut:
Kemudian, metode ekstensi:
Akhirnya, penggunaan yang dimaksud:
Keuntungan yang saya temukan menggunakan pendekatan ini adalah penggunaan kembali
LambdaEqualityComparer
kelas untuk metode lain yang menerimaIEqualityComparer
. (Oh, dan saya menyerahkanyield
barang ke implementasi LINQ asli ...)sumber
Jika Anda memerlukan metode Berbeda pada beberapa properti, Anda dapat melihat perpustakaan PowerfulExtensions saya . Saat ini masih dalam tahap yang sangat muda, tetapi Anda sudah dapat menggunakan metode seperti Distinct, Union, Intersect, Kecuali pada sejumlah properti;
Ini adalah bagaimana Anda menggunakannya:
sumber
Ketika kami menghadapi tugas seperti itu dalam proyek kami, kami mendefinisikan API kecil untuk menyusun komparator.
Jadi, use casenya seperti ini:
Dan API itu sendiri terlihat seperti ini:
Rincian lebih lanjut ada di situs kami: IEqualityComparer di LINQ .
sumber
Anda bisa menggunakan DistinctBy () untuk mendapatkan catatan berbeda oleh properti objek. Cukup tambahkan pernyataan berikut sebelum menggunakannya:
dan kemudian gunakan seperti berikut:
di mana 'Indeks' adalah properti tempat saya ingin data berbeda.
sumber
Anda dapat melakukannya (walaupun tidak secepat kilat) seperti:
Yaitu, "pilih semua orang di mana tidak ada orang lain yang berbeda dalam daftar dengan ID yang sama."
Ingat, dalam contoh Anda, itu hanya akan memilih orang 3. Saya tidak yakin bagaimana mengatakan mana yang Anda inginkan, dari dua sebelumnya.
sumber
Jika Anda tidak ingin menambahkan pustaka MoreLinq ke proyek Anda hanya untuk mendapatkan
DistinctBy
fungsionalitas maka Anda bisa mendapatkan hasil akhir yang sama menggunakan kelebihanDistinct
metode Linq yang membutuhkanIEqualityComparer
argumen.Anda mulai dengan membuat kelas pembanding kesetaraan khusus generik yang menggunakan sintaks lambda untuk melakukan perbandingan kustom dua contoh kelas generik:
Kemudian dalam kode utama Anda, Anda menggunakannya seperti ini:
Voila! :)
Di atas mengasumsikan sebagai berikut:
Person.Id
adalah tipeint
people
koleksi tidak mengandung unsur nolJika koleksi dapat berisi nol maka cukup tulis ulang lambda untuk memeriksa nol, misalnya:
EDIT
Pendekatan ini mirip dengan yang ada di jawaban Vladimir Nesterovsky tetapi lebih sederhana.
Ini juga mirip dengan yang ada di jawaban Joel tetapi memungkinkan untuk logika perbandingan kompleks yang melibatkan beberapa properti.
Namun, jika objek Anda hanya dapat berbeda
Id
saat itu maka pengguna lain memberikan jawaban yang benar bahwa semua yang perlu Anda lakukan adalah mengesampingkan implementasi default dariGetHashCode()
danEquals()
diPerson
kelas Anda dan kemudian hanya menggunakanDistinct()
metode Linq out-of-the-box untuk menyaring duplikat.sumber
Cara terbaik untuk melakukan ini yang akan kompatibel dengan versi .NET lainnya adalah dengan mengesampingkan Persamaan dan GetHash untuk menangani ini (lihat pertanyaan Stack Overflow Kode ini mengembalikan nilai yang berbeda. Namun, yang saya inginkan adalah mengembalikan koleksi yang sangat diketik sebagai lawan dari tipe anonim ), tetapi jika Anda memerlukan sesuatu yang generik di seluruh kode Anda, solusi dalam artikel ini sangat bagus.
sumber
sumber
Select()
new Person
alih-alihnew Player
? Namun, fakta bahwa Anda memesanID
tidak memberitahuDistinct()
untuk menggunakan properti itu dalam menentukan keunikan, jadi ini tidak akan berhasil.Override Equals (object obj) dan GetHashCode () metode:
dan kemudian panggil saja:
sumber
Anda harus dapat mengesampingkan Persamaan pada orang untuk benar-benar melakukan Persamaan di Person.id. Ini seharusnya menghasilkan perilaku yang Anda cari.
sumber
Silakan coba dengan kode di bawah ini.
sumber