शब्दकोश में जोड़ने के विभिन्न तरीके


107

में क्या अंतर है Dictionary.add(key, value)और Dictionary[key] = value?

मैंने देखा है कि ArgumentExceptionडुप्लिकेट कुंजी सम्मिलित करते समय अंतिम संस्करण नहीं फेंकता है , लेकिन क्या पहले संस्करण को पसंद करने का कोई कारण है?

संपादित करें : क्या किसी के पास इस बारे में जानकारी का आधिकारिक स्रोत है? मैं MSDN की कोशिश की है, लेकिन यह हमेशा एक जंगली हंस पीछा के रूप में है :(

जवाबों:


109

प्रदर्शन लगभग 100% समान है। आप Reflector.net में कक्षा खोलकर इसे देख सकते हैं

यह यह सूचकांक है:

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);
    }
}

और यह जोड़ें विधि है:

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

मैं पूरी प्रविष्टि विधि पोस्ट नहीं करूंगा क्योंकि यह बहुत लंबा है, हालांकि विधि घोषणा यह है:

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

और समारोह में और नीचे, यह होता है:

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

यदि जाँचता है कि क्या कुंजी पहले से मौजूद है, और यदि यह करता है और पैरामीटर जोड़ सही है, तो यह अपवाद को फेंकता है।

इसलिए सभी उद्देश्यों और इरादों के लिए प्रदर्शन समान है।

कुछ अन्य उल्लेखों की तरह, यह सभी के बारे में है कि क्या आपको एक ही कुंजी को दो बार जोड़ने के प्रयासों के लिए चेक की आवश्यकता है।

लंबी पोस्ट के लिए क्षमा करें, मुझे आशा है कि यह ठीक है।


+1 बहुत दिलचस्प, आपकी पोस्ट के लिए धन्यवाद! ऐसा लगता है कि प्रदर्शन यहां लगभग समान है, क्योंकि अन्य पोस्टर के बारे में संकेत दिया है, वैसे भी बहुत बढ़िया लगता है :)
सूने रिवर्स

70

पहला संस्करण शब्दकोश में एक नया KeyValuePair जोड़ेगा, यदि कुंजी पहले से ही शब्दकोश में है, तो उसे फेंक दें। इंडेक्सर का उपयोग करने वाला दूसरा, कुंजी नहीं होने पर एक नई जोड़ी जोड़ देगा, लेकिन कुंजी का मान अधिलेखित कर देगा यदि यह पहले से ही शब्दकोश में मौजूद है।

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     

+1 क्या आपको उपरोक्त जानकारी के लिए कोई स्रोत मिला है? मुझे सीखने में दिलचस्पी है अगर पहले या बाद के रूप का उपयोग करने में कोई दुष्प्रभाव या गुहिकायन हैं।
सून रवर्स

3
क्या वास्तव में ऐसा कोई स्रोत नहीं है, जैसे मेरे सिर के ऊपर से, लेकिन मुझे नहीं लगता कि इसके बारे में बहुत कुछ है, अन्य टिप्पणियों में उल्लेख किया गया है। अगर मुझे सही से याद है, तो Add केवल Indexer का उपयोग करता है, लेकिन पहले यह देखने के लिए जांचें कि क्या Key पहले से उपयोग में है।
१३

1
स्टीफन के लिए स्वीकार किए गए उत्तर को बदल दिया गया, क्योंकि उनका प्रलेखन शीर्ष पायदान है। हालांकि यह अभी भी एक महान जवाब है।
सून रवर्स

@Sune: ख़राब चाल ... व्यक्तिगत रूप से मुझे लगता है कि यह जवाब स्टीफन के आगे की सड़क है ... सीधे बिंदु पर और एक सभ्य उदाहरण।
डेमोक्रोडीकेज़

1
@SuneRarios मुझे लगता है, यह लोगों के लिए अधिक सहायक होगा, अगर इसके लिए वर्तमान स्वीकृत उत्तर के बजाय इसका जवाब दिया जाए। क्योंकि यह वास्तव में इस सवाल का जवाब देता है ("अंतर क्या है"), बजाय स्वीकार किए गए एक (जो प्रदर्शन के बारे में बात करता है, और लगभग 99% उपयोगकर्ता इस विषय को खोजते हैं (मेरे जैसे), "अंतर" की आवश्यकता थी (मुझे यह क्यों मिला? विषय), और स्वीकार किए जाते हैं जवाब मुझे और हमारी दूसरी कचरे के लिए बेकार था बजाय, इस सवाल का जवाब सही
T.Todua

30

Dictionary.Add(key, value)और Dictionary[key] = valueअलग उद्देश्य हैं:

  • नई कुंजी / मूल्य जोड़ी Addको जोड़ने के लिए विधि का उपयोग करें , मौजूदा कुंजियों को प्रतिस्थापित नहीं किया जाएगा (एक ArgumentExceptionफेंक दिया गया है)।
  • इंडेक्सर का उपयोग करें यदि आपको परवाह नहीं है कि क्या कुंजी पहले से ही शब्दकोश में मौजूद है, तो दूसरे शब्दों में: कुंजी / मूल्य जोड़ी को जोड़ें यदि कुंजी शब्दकोश में नहीं है या निर्दिष्ट कुंजी के लिए मान को बदलें यदि कुंजी पहले से ही है। शब्दकोश में।

1
कोड जो स्व-वर्णन का आशय महत्वपूर्ण और बेहद मूल्यवान है (और इसके लिए कम-से-कम टिप्पणियों की आवश्यकता है)। यह उत्तर दोनों तरीकों के साथ इरादे में अंतर दिखाता है, और किसी एक को चुनते समय इसका पालन किया जाना चाहिए। दूसरे शब्दों में, 'इंडेक्स ऐड' का उपयोग न करें जब आप समय से पहले जानते हैं कि आप हमेशा जोड़ेंगे, या यहां तक ​​कि हमेशा जोड़ना होगा। IndexOutOfBounds अपवाद होने के बाद अप्रत्याशित व्यवहार से बेहतर है।
ryancdotnet

28

प्रश्न का उत्तर देने के लिए पहले हमें एक शब्दकोश और अंतर्निहित प्रौद्योगिकी के उद्देश्य पर एक नज़र डालने की आवश्यकता है।

Dictionaryवह सूची है KeyValuePair<Tkey, Tvalue>जहाँ प्रत्येक मूल्य को उसकी अद्वितीय कुंजी द्वारा दर्शाया जाता है। मान लीजिए कि हमारे पास आपके पसंदीदा खाद्य पदार्थों की एक सूची है। प्रत्येक मूल्य (भोजन का नाम) इसकी अनूठी कुंजी (एक स्थिति = आपको यह भोजन कितना पसंद है) द्वारा दर्शाया गया है।

उदाहरण कोड:

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

मान लीजिए कि आप स्वस्थ रहना चाहते हैं, आपने अपना मन बदल लिया है और आप अपने पसंदीदा "बर्गर" को सलाद के साथ बदलना चाहते हैं। आपकी सूची अभी भी आपके पसंदीदा की सूची है, आप सूची की प्रकृति को नहीं बदलेंगे। आपका पसंदीदा सूची में नंबर एक बना रहेगा, केवल इसका मूल्य बदल जाएगा। जब आप इसे कहते हैं:

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

लेकिन यह मत भूलो कि आप प्रोग्रामर हैं, और अब से आप अपने वाक्यों को पूरा करते हैं; आप emojis का उपयोग करने से इनकार करते हैं क्योंकि वे संकलन त्रुटि को फेंक देंगे और पसंदीदा की सभी सूची 0 सूचकांक आधारित है।

आपका आहार भी बदल गया! तो आप फिर से अपनी सूची में परिवर्तन करें:

/*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");

परिभाषित करने के साथ दो संभावनाएं हैं, आप या तो पहले मौजूद नहीं कुछ के लिए एक नई परिभाषा देना चाहते हैं या आप पहले से मौजूद परिभाषा को बदलना चाहते हैं।

जोड़ें विधि आपको एक रिकॉर्ड जोड़ने की अनुमति देती है, लेकिन केवल एक शर्त के तहत: इस परिभाषा की कुंजी आपके शब्दकोश में मौजूद नहीं हो सकती है।

अब हम हुड के नीचे देखने जा रहे हैं। जब आप एक डिक्शनरी बना रहे होते हैं, तो आपका कंपाइलर बाल्टी के लिए एक रिज़र्वेशन बनाता है (आपके रिकॉर्ड को स्टोर करने के लिए मेमोरी में रिक्त स्थान)। बाल्टी आपके द्वारा परिभाषित तरीके से कुंजियों को संग्रहीत नहीं करती है। प्रत्येक कुंजी को बकेट में जाने से पहले हैशट किया गया है (Microsoft द्वारा परिभाषित), इस बात का ध्यान रखें कि मूल्य भाग अपरिवर्तित रहता है।

मैं अपने उदाहरण को सरल बनाने के लिए CRC32 हैशिंग एल्गोरिथ्म का उपयोग करूँगा। जब आप परिभाषित करते हैं:

myDietFavorites[0] = "Pizza";

बाल्टी में क्या जा रहा है db2dc565 "पिज़्ज़ा" (सरलीकृत) है।

जब आप मान को इसमें बदलते हैं:

myDietFavorites[0] = "Spaghetti";

आपके पास अपना 0 है जो फिर db2dc565 है फिर आप अपने बाल्टी में इस मान को ढूंढते हैं कि क्या यह वहां है। यदि यह वहां है तो आप बस कुंजी को सौंपे गए मूल्य को फिर से लिखेंगे। यदि यह वहाँ नहीं है तो आप बाल्टी में अपना मूल्य रख देंगे।

जब आप अपने शब्दकोश में फ़ंक्शन जोड़ें जैसे कहते हैं:

myDietFavorite.Add(0, "Chocolate");

आप अपने 0 हैश की तुलना बाल्टी में रखने वालों से करते हैं। आप इसे बाल्टी में तभी रख सकते हैं जब यह वहां न हो

यह जानना महत्वपूर्ण है कि यह विशेष रूप से कैसे काम करता है यदि आप स्ट्रिंग या चार प्रकार की कुंजी के शब्दकोश के साथ काम करते हैं। हैशिंग से गुजरने के कारण यह संवेदनशील है। इसलिए उदाहरण के लिए "नाम"! = "नाम"। इसका चित्रण करने के लिए हमारे CRC32 का उपयोग करें।

"नाम" का मान है: e04112b1 "नाम" का मान है: 1107fb5b


यह दो लाइन समझने के लिए पर्याप्त है ....... परिभाषित करने के साथ दो संभावनाएं हैं, आप या तो पहले मौजूद नहीं कुछ के लिए एक नई परिभाषा देना चाहते हैं या आप पहले से मौजूद परिभाषा को बदलना चाहते हैं। जोड़ें विधि आपको एक रिकॉर्ड जोड़ने की अनुमति देती है, लेकिन केवल एक शर्त के तहत: इस परिभाषा की कुंजी आपके शब्दकोश में मौजूद नहीं हो सकती है।
नीरज त्रिवेदी

4

हां, यह अंतर है, यदि कोई कुंजी पहले से मौजूद है, तो ऐड मेथड एक अपवाद फेंकता है।

ऐड पद्धति का उपयोग करने का कारण बिल्कुल यही है। यदि शब्दकोश में पहले से ही कुंजी शामिल नहीं है, तो आप आमतौर पर अपवाद चाहते हैं ताकि आपको समस्या से अवगत कराया जाए।


0

प्रदर्शन में संभावित समानता से अधिक, यह देखते हुए कि आपके द्वारा उपयोग किए जा रहे कोड के टुकड़े के लिए अधिक सही और पठनीय लगता है।

मुझे लगता है कि एक ऑपरेशन है जो एक अतिरिक्त का वर्णन करता है, कुंजी की उपस्थिति पहले से ही वास्तव में दुर्लभ अपवाद है जो कि ऐड के साथ सबसे अच्छा प्रतिनिधित्व करता है। शब्दार्थ यह अधिक समझ में आता है।

dict[key] = valueबेहतर प्रतिस्थापन का प्रतिनिधित्व करता है। अगर मुझे वह कोड दिखाई देता है, तो मुझे लगता है कि कुंजी पहले से ही वैसे भी शब्दकोश में होने की उम्मीद है।


मुझे लगता है कि कुंजी पहले मौजूद है या नहीं यह जाँचने से एक छोटा सा प्रदर्शन लाभ है। मुझे उम्मीद नहीं थी dic[key] = valueकि कुंजी पहले से ही मौजूद थी, लेकिन मुझे लगता है कि यह बहस का मुद्दा है;)
सुनीर रिवर्स

2
+ मुझे लगता है कि अगर पहले से ही प्रतिनिधित्व किया गया है, तो फेंकने का उपयोग कभी भी जांच के तरीके के रूप में नहीं किया जाना चाहिए। if (स्ट्रिंग्स .ContainsKey ("foo")) strings.Add ("फू", "बार");
hhravn

0

कोई एक मान प्रदान कर रहा है जबकि दूसरा शब्दकोश में एक नई कुंजी और मूल्य जोड़ रहा है।


0

शब्दकोश में मान सम्मिलित करने के लिए

 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.