Saya ingin membandingkan konten beberapa koleksi dalam metode Persamaan saya. Saya memiliki Kamus dan IList. Apakah ada metode bawaan untuk melakukan ini?
Diedit: Saya ingin membandingkan dua Kamus dan dua ILIST, jadi saya pikir apa artinya kesetaraan itu jelas - jika dua kamus berisi kunci yang sama yang dipetakan dengan nilai yang sama, maka keduanya sama.
c#
.net
collections
TIMK
sumber
sumber
IList
? Pertanyaan tidak jelas.Enumerable.SequenceEqual
danISet.SetEquals
menyediakan versi fungsi ini. Jika Anda ingin menjadi agnostik ketertiban dan bekerja dengan koleksi yang memiliki duplikat, Anda harus menggulirnya sendiri. Lihatlah penerapan yang disarankan dalam pos iniJawaban:
Enumerable.SequenceEqual
Anda tidak dapat langsung membandingkan daftar & kamus, tetapi Anda bisa membandingkan daftar nilai dari Kamus dengan daftar
sumber
.Keys
dan.Values
dapat mengembalikan kunci dan nilai dalam urutan apa pun yang mereka suka, dan urutan itu kemungkinan akan berubah karena kamus juga dimodifikasi. Saya sarankan Anda membaca apa itu Kamus dan bukan.Seperti yang disarankan dan dicatat oleh orang lain,
SequenceEqual
peka terhadap pesanan. Untuk mengatasinya, Anda bisa mengurutkan kamus dengan kunci (yang unik, dan karenanya selalu stabil) dan kemudian gunakanSequenceEqual
. Ungkapan berikut memeriksa apakah dua kamus sama tanpa memandang urutan internalnya:EDIT: Seperti yang ditunjukkan oleh Jeppe Stig Nielsen, beberapa objek memiliki
IComparer<T>
yang tidak sesuai dengan merekaIEqualityComparer<T>
, menghasilkan hasil yang salah. Saat menggunakan kunci dengan objek seperti itu, Anda harus menentukan yang benarIComparer<T>
untuk kunci-kunci itu. Misalnya, dengan kunci string (yang menunjukkan masalah ini), Anda harus melakukan hal berikut untuk mendapatkan hasil yang benar:sumber
CompareTo
? Solusi Anda akan meledak kemudian. Bagaimana jika jenis kunci memiliki pembanding default yang tidak kompatibel dengan pembanding kesetaraan standarnya? Ini masalahnyastring
, Anda tahu. Sebagai contoh, kamus-kamus ini (dengan pembanding kesetaraan standar implisit) akan gagal dalam ujian Anda (berdasarkan semua info budaya yang saya ketahui):var dictionary1 = new Dictionary<string, int> { { "Strasse", 10 }, { "Straße", 20 }, }; var dictionary2 = new Dictionary<string, int> { { "Straße", 20 }, { "Strasse", 10 }, };
IComparer
danIEqualityComparer
- Saya tidak mengetahui masalah ini, sangat menarik! Saya memperbarui jawabannya dengan solusi yang memungkinkan. Tentang kurangnyaCompareTo
, saya pikir pengembang harus memastikan delegasi yang disediakan untukOrderBy()
metode mengembalikan sesuatu yang sebanding. Saya pikir ini berlaku untuk penggunaan apa pun atauOrderBy()
, bahkan di luar perbandingan kamus.Selain SequenceEqual yang disebutkan , yang
(yang mungkin merupakan pembanding default, yaitu overriden
Equals()
)Perlu disebutkan bahwa dalam. Net4 ada SetEquals pada
ISet
objek, yangJadi jika Anda ingin memiliki daftar objek, tetapi mereka tidak perlu dalam urutan tertentu, pertimbangkan bahwa
ISet
(seperti aHashSet
) mungkin merupakan pilihan yang tepat.sumber
Lihatlah metode Enumerable.SequenceEqual
sumber
.NET Tidak memiliki alat yang ampuh untuk membandingkan koleksi. Saya telah mengembangkan solusi sederhana yang dapat Anda temukan di tautan di bawah:
http://robertbouillon.com/2010/04/29/comparing-collections-in-net/
Ini akan melakukan perbandingan kesetaraan terlepas dari pesanan:
Ini akan memeriksa untuk melihat apakah item ditambahkan / dihapus:
Ini akan melihat item apa dalam kamus berubah:
sumber
.Removed
sama denganlist1.Except(list2)
,.Added
adalahlist2.Except(list1)
,.Equal
adalahlist1.Intersect(list2)
dan.Different
sekarangoriginal.Join(changed, left => left.Key, right => right.Key, (left, right) => left.Value == right.Value)
. Anda dapat melakukan hampir semua perbandingan dengan LINQ..Different
adalahoriginal.Join(changed, left => left.Key, right => right.Key, (left, right) => new { Key = left.Key, NewValue = right.Value, Different = left.Value == right.Value).Where(d => d.Different)
. Dan Anda bahkan dapat menambahkanOldValue = left.Value
jika Anda membutuhkan nilai lama juga.Saya tidak tahu tentang metode Enumerable.SequenceEqual (Anda belajar sesuatu setiap hari ....), tapi saya akan menyarankan menggunakan metode ekstensi; sesuatu seperti ini:
Cukup menarik, setelah mengambil 2 detik untuk membaca tentang SequenceEqual, sepertinya Microsoft telah membangun fungsi yang saya jelaskan untuk Anda.
sumber
Ini tidak langsung menjawab pertanyaan Anda, tetapi MS TestTools dan NUnit menyediakan
yang melakukan apa yang Anda inginkan.
sumber
Untuk membandingkan koleksi, Anda juga dapat menggunakan LINQ.
Enumerable.Intersect
mengembalikan semua pasangan yang sama. Anda dapat membuat dua kamus seperti ini:Diperlukan perbandingan pertama karena
dict2
dapat memuat semua kunci daridict1
dan banyak lagi.Anda juga dapat menggunakan memikirkan variasi menggunakan
Enumerable.Except
danEnumerable.Union
yang mengarah ke hasil yang serupa. Tetapi dapat digunakan untuk menentukan perbedaan yang tepat antara set.sumber
Bagaimana dengan contoh ini:
Courtesy: https://www.dotnetperls.com/dictionary-equals
sumber
Untuk koleksi yang dipesan (Daftar, Array) gunakan
SequenceEqual
untuk penggunaan HashSet
SetEquals
untuk Kamus dapat Anda lakukan:
(Solusi yang lebih optimal akan menggunakan penyortiran tetapi itu akan membutuhkan
IComparable<TValue>
)sumber
Tidak. Kerangka koleksi tidak memiliki konsep kesetaraan. Jika Anda memikirkannya, tidak ada cara membandingkan koleksi yang tidak subjektif. Misalnya membandingkan IList Anda dengan Kamus Anda, apakah mereka akan sama jika semua kunci ada di IList, semua nilai ada di IList atau jika keduanya ada di IList? Tidak ada cara yang jelas untuk membandingkan kedua koleksi ini tanpa pengetahuan tentang apa yang akan mereka gunakan sehingga tujuan umum sama dengan metode tidak masuk akal.
sumber
Tidak, karena kerangka kerja tidak tahu bagaimana membandingkan konten daftar Anda.
Lihatlah ini:
http://blogs.msdn.com/abhinaba/archive/2005/10/11/479537.aspx
sumber
IComparer<T>
, Overrideobject.Equals
,IEquatable<T>
,IComparable<T>
...sumber
Tidak ada, tidak dan mungkin tidak, setidaknya saya akan percaya begitu. Alasan di baliknya adalah kesetaraan koleksi mungkin merupakan perilaku yang ditentukan pengguna.
Elemen dalam koleksi tidak seharusnya dalam urutan tertentu meskipun mereka memiliki pemesanan secara alami, itu bukan apa yang harus mengandalkan algoritma pembanding. Katakanlah Anda memiliki dua koleksi:
Apakah mereka setara atau tidak? Anda harus tahu tetapi saya tidak tahu apa sudut pandang Anda.
Koleksi secara konsep tidak teratur secara default, hingga algoritme menyediakan aturan penyortiran. Hal yang sama dengan SQL server akan menarik perhatian Anda adalah ketika Anda mencoba melakukan pagination, itu mengharuskan Anda untuk memberikan aturan penyortiran:
https://docs.microsoft.com/en-US/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-2017
Dua koleksi lagi:
Sekali lagi, apakah mereka setara atau tidak? Katakan pada saya ..
Pengulangan elemen koleksi memainkan perannya dalam skenario yang berbeda dan beberapa koleksi seperti
Dictionary<TKey, TValue>
bahkan tidak memungkinkan elemen berulang.Saya percaya jenis kesetaraan ini adalah aplikasi yang ditentukan dan oleh karena itu kerangka kerjanya tidak menyediakan semua kemungkinan implementasi.
Nah, dalam kasus umum
Enumerable.SequenceEqual
cukup baik tetapi mengembalikan false dalam kasus berikut:Saya membaca beberapa jawaban untuk pertanyaan seperti ini (Anda dapat menggunakan google untuk itu) dan apa yang akan saya gunakan, secara umum:
Itu berarti satu koleksi mewakili yang lain dalam elemen mereka termasuk waktu yang berulang tanpa memperhitungkan urutan aslinya. Beberapa catatan implementasi:
GetHashCode()
hanya untuk pemesanan bukan untuk kesetaraan; Saya pikir sudah cukup dalam hal iniCount()
tidak akan benar - benar menyebutkan koleksi dan langsung jatuh ke dalam implementasi propertiICollection<T>.Count
Jika referensi sama, itu hanya Boris
sumber