Saya mencoba membuat tabel pencarian Kamus di C #. Saya perlu menyelesaikan 3-tuple nilai menjadi satu string. Saya mencoba menggunakan array sebagai kunci, tetapi tidak berhasil, dan saya tidak tahu harus berbuat apa lagi. Pada titik ini saya sedang mempertimbangkan untuk membuat Dictionary of Dictionaries of Dictionaries, tetapi itu mungkin tidak terlalu bagus untuk dilihat, meskipun begitulah cara saya melakukannya dalam javascript.
c#
dictionary
hashtable
tuples
AlexH
sumber
sumber
GetHashCode
Penerapan Anda tidak terlalu baik. Itu tidak berubah di bawah permutasi bidang.new object()
sama dengan yang lainnew object()
? Ini tidak hanya menggunakan perbandingan referensi langsung ... coba:bool test = new Tuple<int, string>(1, "foo").Equals(new Tuple<int, string>(1, "Foo".ToLower()));
Antara pendekatan berbasis kamus tuple dan bersarang, hampir selalu lebih baik untuk menggunakan berbasis tupel.
Dari sudut pandang pemeliharaan ,
jauh lebih mudah untuk mengimplementasikan fungsionalitas yang terlihat seperti:
dari
dari sisi callee. Dalam kasus kedua, setiap penambahan, pencarian, penghapusan, dll memerlukan tindakan pada lebih dari satu kamus.
Selain itu, jika kunci komposit Anda memerlukan satu bidang lagi (atau kurang) di masa mendatang, Anda perlu mengubah banyak kode dalam kasus kedua (kamus bertingkat) karena Anda harus menambahkan kamus bertingkat lebih lanjut dan pemeriksaan berikutnya.
Dari perspektif kinerja , kesimpulan terbaik yang bisa Anda capai adalah dengan mengukurnya sendiri. Tetapi ada beberapa batasan teoretis yang dapat Anda pertimbangkan sebelumnya:
Dalam kasus kamus bersarang, memiliki kamus tambahan untuk setiap kunci (luar dan dalam) akan memiliki beberapa overhead memori (lebih dari apa yang akan membuat tupel).
Dalam kasus kamus bersarang, setiap tindakan dasar seperti penambahan, pembaruan, pencarian, penghapusan, dll perlu dilakukan dalam dua kamus. Sekarang ada kasus di mana pendekatan kamus bersarang bisa lebih cepat, yaitu, ketika data yang dicari tidak ada, karena kamus perantara dapat melewati penghitungan & perbandingan kode hash lengkap, tetapi sekali lagi itu harus diatur waktunya untuk memastikan. Jika ada data, ini harus lebih lambat karena pencarian harus dilakukan dua kali (atau tiga kali bergantung pada penumpukan).
Mengenai pendekatan tupel, tupel .NET bukanlah yang paling berkinerja ketika dimaksudkan untuk digunakan sebagai kunci dalam set karena implementasinya
Equals
danGetHashCode
menyebabkan tinju untuk jenis nilai .Saya akan menggunakan kamus berbasis tupel, tetapi jika saya menginginkan kinerja lebih, saya akan menggunakan tupel saya sendiri dengan implementasi yang lebih baik.
Di samping catatan, beberapa kosmetik dapat membuat kamus keren:
Panggilan bergaya pengindeks bisa jauh lebih bersih dan intuitif. Misalnya,
Jadi tunjukkan pengindeks yang diperlukan dalam kelas kamus Anda yang secara internal menangani penyisipan dan pencarian.
Selain itu, terapkan
IEnumerable
antarmuka yang sesuai dan berikanAdd(TypeA, TypeB, TypeC, string)
metode yang akan memberi Anda sintaks penginisialisasi koleksi, seperti:sumber
string foo = dict[a][b][c]
:?a
,. Anda bisa saja mengulang kamus apa pun seperti koleksi biasa dan memeriksa properti kunci jika yaa
. Jika Anda selalu ingin mendapatkan item di dict by first property maka Anda dapat mendesain kamus dengan lebih baik sebagai kamus kamus seperti yang ditunjukkan dalam jawaban saya dan kueri sepertidict[a]
, yang memberi Anda kamus lain.4
untuk kedua kuncia
danb
, maka Anda bisa menjadikannya kamus standar dan menambahkan nilai sepertidict[a] = 4
dandict[b] = 4
. Mungkin tidak masuk akal jika secara logis Andaa
danb
harus menjadi satu unit. Dalam kasus seperti itu, Anda dapat menentukan kustomIEqualityComparer
yang menyamakan dua contoh kunci sama jika salah satu propertinya sama. Semua ini secara umum dapat dilakukan dengan refelction.Jika Anda menggunakan C # 7, Anda harus mempertimbangkan untuk menggunakan tupel nilai sebagai kunci komposit Anda. Tupel nilai biasanya menawarkan kinerja yang lebih baik daripada tupel referensi tradisional (
Tuple<T1, …>
) karena tupel nilai adalah tipe nilai (struct), bukan tipe referensi, sehingga menghindari alokasi memori dan biaya pengumpulan sampah. Selain itu, mereka menawarkan sintaks yang ringkas dan lebih intuitif, memungkinkan bidang mereka diberi nama jika Anda menginginkannya. Mereka juga mengimplementasikanIEquatable<T>
antarmuka yang dibutuhkan untuk kamus.sumber
Cara yang baik, bersih, cepat, mudah dan mudah dibaca adalah:
tambahkan sesuatu yang mirip seperti ini:
Jadi Anda bisa menggunakannya dengan kamus:
sumber
public TypeA DataA => Item1;
Jika karena alasan tertentu Anda benar-benar ingin menghindari membuat kelas Tuple Anda sendiri, atau menggunakan built-in ke dalam .NET 4.0, ada satu pendekatan lain yang mungkin; Anda dapat menggabungkan tiga nilai kunci menjadi satu nilai.
Misalnya, jika ketiga nilai adalah tipe integer bersama-sama yang tidak mengambil lebih dari 64 bit, Anda dapat menggabungkannya menjadi
ulong
.Kasus terburuk Anda selalu dapat menggunakan string, selama Anda memastikan tiga komponen di dalamnya dibatasi dengan beberapa karakter atau urutan yang tidak terjadi di dalam komponen kunci, misalnya, dengan tiga angka yang dapat Anda coba:
Jelas ada beberapa overhead komposisi dalam pendekatan ini, tetapi tergantung pada apa yang Anda gunakan untuk ini mungkin cukup sepele untuk tidak memedulikannya.
sumber
JavaScriptSerializer
untuk menggabungkan array string dan / atau tipe integer untuk Anda. Dengan cara ini, Anda tidak perlu membuat sendiri karakter pembatas.key1
,key2
,key3
) adalah string yang berisi deliminator ("#"
)Saya akan mengganti Tuple Anda dengan GetHashCode yang tepat, dan hanya menggunakannya sebagai kuncinya.
Selama Anda membebani metode yang tepat, Anda akan melihat kinerja yang layak.
sumber
Berikut adalah tupel .NET untuk referensi:
sumber
Jika kode konsumsi Anda dapat dilakukan dengan antarmuka IDictionary <>, alih-alih Kamus, naluri saya akan menggunakan SortedDictionary <> dengan pembanding array kustom, yaitu:
Dan buatlah demikian (menggunakan int [] hanya untuk contoh konkret):
sumber