Berbagai cara menambahkan ke Kamus

107

Apa perbedaan Dictionary.add(key, value)dan Dictionary[key] = value?

Saya perhatikan bahwa versi terakhir tidak melempar ArgumentExceptionketika memasukkan kunci duplikat, tetapi adakah alasan untuk memilih versi pertama?

Sunting : Apakah ada yang memiliki sumber informasi resmi tentang ini? Saya sudah mencoba MSDN, tetapi itu selalu sia-sia :(

Sune Rievers
sumber

Jawaban:

109

Performanya hampir 100% identik. Anda dapat memeriksanya dengan membuka kelas di Reflector.net

Ini adalah pengindeks ini:

public TValue this[TKey key]
{
    get
    {
        int index = this.FindEntry(key);
        if (index >= 0)
        {
            return this.entries[index].value;
        }
        ThrowHelper.ThrowKeyNotFoundException();
        return default(TValue);
    }
    set
    {
        this.Insert(key, value, false);
    }
}

Dan ini adalah metode Add:

public void Add(TKey key, TValue value)
{
    this.Insert(key, value, true);
}

Saya tidak akan memposting seluruh metode Sisipkan karena agak panjang, namun deklarasi metode adalah ini:

private void Insert(TKey key, TValue value, bool add)

Dan lebih jauh di dalam fungsinya, ini terjadi:

if ((this.entries[i].hashCode == num) && this.comparer.Equals(this.entries[i].key, key))
{
    if (add)
    {
        ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
    }

Yang memeriksa apakah kunci sudah ada, dan jika ada dan parameter yang ditambahkan benar, itu akan memunculkan pengecualian.

Jadi untuk semua tujuan dan maksud kinerjanya sama.

Seperti beberapa sebutan lainnya, ini semua tentang apakah Anda memerlukan cek tersebut, untuk upaya menambahkan kunci yang sama dua kali.

Maaf untuk posting yang panjang, saya harap tidak apa-apa.

Steffen
sumber
+1 Sangat menarik, terima kasih atas kiriman Anda! Tampaknya kinerja hampir identik di sini, seperti yang diisyaratkan oleh poster lain, bagaimanapun juga, penemuan hebat :)
Sune Rievers
70

Versi pertama akan menambahkan KeyValuePair baru ke kamus, menampilkan jika kunci sudah ada dalam kamus. Yang kedua, menggunakan pengindeks, akan menambahkan pasangan baru jika kunci tidak ada, tetapi menimpa nilai kunci jika sudah ada di kamus.

IDictionary<string, string> strings = new Dictionary<string, string>();

strings["foo"] = "bar";          //strings["foo"] == "bar"
strings["foo"] = string.Empty;   //strings["foo"] == string.empty
strings.Add("foo", "bar");       //throws     
hhravn
sumber
+1 Apakah Anda sudah mendapatkan sumber untuk informasi di atas? Saya tertarik untuk mempelajari apakah ada efek samping atau peringatan dalam menggunakan bentuk pertama atau terakhir.
Sune Rievers
3
Tidak benar-benar memiliki sumber seperti itu, hanya di atas kepala saya, tetapi saya tidak berpikir ada lebih banyak dari itu, daripada yang disebutkan di komentar lain. Jika saya ingat dengan benar, Tambah hanya menggunakan pengindeks, tetapi periksa terlebih dahulu untuk melihat apakah Kunci sudah digunakan.
hhravn
1
Mengubah jawaban yang diterima untuk Steffen, karena dokumentasinya adalah yang terbaik. Ini masih merupakan jawaban yang bagus.
Sune Rievers
@ Sune: Langkah buruk ... secara pribadi saya pikir jawaban ini adalah jalan di depan Steffen ... langsung ke intinya dan contoh yang layak.
demoncodemonkey
1
@SuneRievers Saya pikir, akan lebih membantu orang-orang, jika menerima jawaban untuk ini, daripada jawaban yang diterima saat ini. Karena ini benar-benar menjawab pertanyaan ("apa bedanya"), daripada yang diterima (yang berbicara tentang kinerja, dan hampir 99% pengguna yang menelusuri topik ini (seperti saya), membutuhkan "perbedaan" (apa alasan saya bertemu ini topik), dan jawaban yang diterima tidak berguna bagi saya dan menyia-nyiakan yang kedua. sebaliknya, jawaban ini tepat.
T.Todua
30

Dictionary.Add(key, value)dan Dictionary[key] = valuememiliki tujuan yang berbeda:

  • Gunakan Addmetode untuk menambahkan pasangan kunci / nilai baru, kunci yang ada tidak akan diganti (dan ArgumentExceptiondilempar).
  • Gunakan pengindeks jika Anda tidak peduli apakah kunci tersebut sudah ada dalam kamus, dengan kata lain: tambahkan pasangan kunci / nilai jika kunci tidak ada dalam kamus atau ganti nilai untuk kunci yang ditentukan jika kuncinya sudah ada di kamus.
Michael Damatov
sumber
1
Kode yang menggambarkan niat sendiri adalah penting dan sangat berharga (dan memerlukan sedikit komentar). Jawaban ini menunjukkan perbedaan maksud dengan kedua metode tersebut, dan harus diikuti saat memilih salah satu. Dengan kata lain, jangan gunakan 'indexer add' bila Anda tahu sebelumnya bahwa Anda akan selalu menambahkan, atau bahkan harus selalu menambahkan. Memiliki pengecualian IndexOutOfBounds dilempar lebih baik daripada perilaku yang tidak terduga.
ryancdotnet
28

Untuk menjawab pertanyaan pertama kita perlu melihat tujuan kamus dan teknologi yang mendasari.

Dictionaryadalah daftar di KeyValuePair<Tkey, Tvalue>mana setiap nilai diwakili oleh kunci uniknya. Katakanlah kami memiliki daftar makanan favorit Anda. Setiap nilai (nama makanan) diwakili oleh kunci uniknya (posisi = seberapa Anda menyukai makanan ini).

Kode contoh:

Dictionary<int, string> myDietFavorites = new Dictionary<int, string>()
{
    { 1, "Burger"},
    { 2, "Fries"},
    { 3, "Donuts"}
};

Katakanlah Anda ingin tetap sehat, Anda berubah pikiran dan Anda ingin mengganti "Burger" favorit Anda dengan salad. Daftar Anda tetap menjadi daftar favorit Anda, Anda tidak akan mengubah sifat daftar. Favorit Anda akan tetap menjadi nomor satu di daftar, hanya nilainya yang akan berubah. Ini adalah saat Anda menyebutnya:

/*your key stays 1, you only replace the value assigned to this key
  you alter existing record in your dictionary*/
myDietFavorites[1] = "Salad";

Tapi jangan lupa Anda adalah programmernya, dan mulai sekarang Anda menyelesaikan kalimat Anda dengan; Anda menolak untuk menggunakan emoji karena akan menimbulkan kesalahan kompilasi dan semua daftar favorit berbasis indeks 0.

Diet Anda juga berubah! Jadi Anda mengubah daftar Anda lagi:

/*you don't want to replace Salad, you want to add this new fancy 0
  position to your list. It wasn't there before so you can either define it*/
myDietFavorites[0] = "Pizza";

/*or Add it*/
myDietFavorites.Add(0, "Pizza");

Ada dua kemungkinan dalam mendefinisikan, Anda ingin memberikan definisi baru untuk sesuatu yang belum ada sebelumnya atau Anda ingin mengubah definisi yang sudah ada.

Add method memungkinkan Anda untuk menambahkan record tetapi hanya dengan satu syarat: kunci untuk definisi ini mungkin tidak ada dalam kamus Anda.

Sekarang kita akan melihat di bawah tenda. Saat Anda membuat kamus, kompiler Anda membuat reservasi untuk bucket (spasi dalam memori untuk menyimpan catatan Anda). Bucket tidak menyimpan kunci dengan cara Anda mendefinisikannya. Setiap kunci di-hash sebelum pergi ke bucket (ditentukan oleh Microsoft), perlu disebutkan bahwa bagian nilai tetap tidak berubah.

Saya akan menggunakan algoritma hashing CRC32 untuk menyederhanakan contoh saya. Saat Anda mendefinisikan:

myDietFavorites[0] = "Pizza";

Apa yang akan ke ember adalah db2dc565 "Pizza" (disederhanakan).

Saat Anda mengubah nilainya dengan:

myDietFavorites[0] = "Spaghetti";

Anda hash 0 Anda yang lagi db2dc565 lalu Anda mencari nilai ini di keranjang Anda untuk menemukan apakah itu ada. Jika ada, Anda cukup menulis ulang nilai yang ditetapkan ke kunci tersebut. Jika tidak ada, Anda akan menempatkan nilai Anda di keranjang.

Saat Anda memanggil fungsi Add di kamus Anda seperti:

myDietFavorite.Add(0, "Chocolate");

Anda melakukan hash 0 untuk membandingkan nilainya dengan nilai di bucket. Anda boleh memasukkannya ke dalam ember hanya jika tidak ada .

Sangat penting untuk mengetahui cara kerjanya terutama jika Anda bekerja dengan kamus kunci jenis string atau char. Peka huruf besar / kecil karena menjalani hashing. Jadi misalnya "nama"! = "Nama". Mari gunakan CRC32 kami untuk menggambarkan ini.

Nilai untuk "nama" adalah: e04112b1 Nilai untuk "Nama" adalah: 1107fb5b

Kamil Kurzynowski
sumber
Dua baris ini sudah cukup untuk dipahami ....... Ada dua kemungkinan dengan definisi, Anda ingin memberikan definisi baru untuk sesuatu yang belum ada atau Anda ingin mengubah definisi yang sudah ada. Add method memungkinkan Anda untuk menambahkan record tetapi hanya dengan satu syarat: kunci untuk definisi ini mungkin tidak ada dalam kamus Anda.
Niraj Trivedi
4

Ya, itulah perbedaannya, metode Add akan mengeluarkan pengecualian jika kuncinya sudah ada.

Alasan untuk menggunakan metode Tambah persis seperti ini. Jika kamus tidak seharusnya berisi kunci tersebut, Anda biasanya menginginkan pengecualian agar Anda mengetahui masalahnya.

Guffa
sumber
0

Mengingat, kemungkinan besar kemiripan dalam performa, gunakan apa pun yang dirasa lebih tepat dan dapat dibaca oleh bagian kode yang Anda gunakan.

Saya merasakan operasi yang mendeskripsikan penambahan, karena keberadaan kunci sudah merupakan pengecualian yang sangat langka paling baik diwakili dengan penambahan. Secara semantik, ini lebih masuk akal.

Itu dict[key] = valuemewakili substitusi yang lebih baik. Jika saya melihat kode itu, saya setengah berharap kuncinya sudah ada di kamus.

Jorge Córdoba
sumber
Saya akan berasumsi ada keuntungan kinerja kecil dari tidak memeriksa apakah kunci ada terlebih dahulu. Saya tidak berharap dari dic[key] = valueitu kuncinya sudah ada, tapi saya rasa itu bisa diperdebatkan;)
Sune Rievers
2
+ Saya pikir melempar tidak boleh digunakan sebagai cara untuk memeriksa apakah kuncinya sudah ada. if (! strings.ContainsKey ("foo")) strings.Add ("foo", "bar");
hhravn
0

Salah satunya adalah memberikan nilai sementara yang lainnya menambahkan Key and Value baru ke Dictionary.

Joshua Smith
sumber
0

Untuk memasukkan Nilai ke dalam Kamus

 Dictionary<string, string> dDS1 = new Dictionary<string, string>();//Declaration
 dDS1.Add("VEqpt", "aaaa");//adding key and value into the dictionary
 string Count = dDS1["VEqpt"];//assigning the value of dictionary key to Count variable
 dDS1["VEqpt"] = Count + "bbbb";//assigning the value to key
Maghalakshmi Saravana
sumber