2012-02-29 23 views
8

रूबी आप हैश के लिए डिफ़ॉल्ट मान परिभाषित करने देता है संशोधित करना:डिफ़ॉल्ट हैश मान

h=Hash.new(['alright']) 
h['meh'] # => ["alright"] 

एक मूल्य के असाइनमेंट पता चलता है जब हैश प्रदर्शित, लेकिन एक संशोधित डिफ़ॉल्ट नहीं करता है। 'bad' कहां है?

h['good']=['fine','dandy'] 
h['bad'].push('unhappy') 
h # => {"good"=>["fine", "dandy"]} 

'bad' दिखाता है कि अगर हम स्पष्ट रूप से पूछते हैं।

h['bad'] # => ["alright", "unhappy"] 

हैश प्रदर्शित करते समय संशोधित डिफ़ॉल्ट मान क्यों दिखाई नहीं देता है?

+0

वैध प्रश्न, लेकिन यह शायद एक डुप्लिकेट है। –

उत्तर

11

हैश के डिफ़ॉल्ट मान नहीं है काम की तरह आप इसकी उम्मीद कर रहे हैं। जब आप कहते हैं कि h[k], प्रक्रिया इस प्रकार है:

  1. अगर हम एक k कुंजी है, अपने मूल्य वापसी।
  2. यदि हमारे पास हैश के लिए डिफ़ॉल्ट मान है, तो उस डिफ़ॉल्ट मान को वापस करें।
  3. यदि हमारे पास डिफ़ॉल्ट मान प्रदान करने के लिए ब्लॉक है, तो ब्लॉक निष्पादित करें और उसका वापसी मूल्य वापस करें।

ध्यान दें कि (2) और (3) हैश में k डालने के बारे में कुछ भी नहीं कहें। डिफ़ॉल्ट मान अनिवार्य रूप से इस में h[k] बदल जाता है:

h.has_key?(k) ? h[k] : the_default_value 

तो बस एक गैर existant कुंजी तक पहुँचने और डिफ़ॉल्ट मान वापस पाने हैश को लापता कुंजी नहीं जोड़ा जाएगा।

इसके अलावा, फार्म की कुछ भी:

Hash.new([ ... ]) 
# or 
Hash.new({ ... }) 

लगभग हमेशा एक गलती के रूप में आप के लिए ठीक उसी डिफ़ॉल्ट सरणी या हैश साझा करेंगे है सभी मूलभूत मूल्यों के लिए। उदाहरण के लिए, यदि आप ऐसा करते हैं:

h = Hash.new(['a']) 
h[:k].push('b') 

फिर h[:i], h[:j] ... सभी ['a', 'b'] वापस आ जाएगी और शायद ही कभी तुम क्या चाहते हो।

मुझे लगता है कि आप block form of the default value लिए देख रहे हैं:

h = Hash.new { |h, k| h[k] = [ 'alright' ] } 

कि दो काम करने होंगे:

  1. किसी गैर-मौजूद कुंजी को एक्सेस करना हैश है कि कुंजी जोड़ना होगा और यह होगा प्रदान किया गया ऐरे इसके मूल्य के रूप में।
  2. सभी डिफ़ॉल्ट मान अलग-अलग वस्तुएं होंगी, इसलिए कोई बदलना बाकी को बदल नहीं पाएगा।
2

क्या हुआ है आप h['bad'] पर ing 'दुखी' हैश का डिफ़ॉल्ट मान संशोधित, push द्वारा होता है। क्या आप नहीं किया है वास्तव में हैश में 'खराब' जोड़ा गया है, यही कारण है कि जब आप h का निरीक्षण करते हैं तो यह प्रदर्शित नहीं होता है।

>> p h['bleh'] 
=> ["allright", "unhappy"] 

जो निश्चित रूप से मेरे लिए पता चलता है कि डिफ़ॉल्ट मान बदल दिया गया है:

सभी कोड आप आपूर्ति के बाद, मैं इस कोशिश की। अपने प्रश्न का उत्तर में 'क्यों संशोधित डिफ़ॉल्ट दिखाई नहीं करता है जब हैश प्रदर्शित?', आप इसे करने के लिए एक तत्व जोड़ने के लिए है, बजाय बस इसे तक पहुँचने के लिए होता है:

>> h['bleh'] # Doesn't add 'bleh' to the hash 
>> p h 
=> {"good"=>["fine", "dandy"]} # See, no extra values 

>> h['bleh'] = h.default # Does add a new key with the default value 
>> p h 
=> {"good"=>["fine", "dandy"], "bleh"=>["allright", "unhappy"]} 
+1

वाह। मैं पूरी तरह से सही खड़ा हूँ। लेकिन अब मैं इस मामले में क्यों फंस गया हूं। [] एक हैश ऑब्जेक्ट पर एक विधि है, जो परिणाम देता है। उस परिवर्तन को धक्का भेजना डिफ़ॉल्ट हैश क्यों बदलता है? रूबी स्रोत कोड के माध्यम से खुदाई शुरू करने का समय ... –

+0

समझ गया। हैश ऑब्जेक्ट में अभी भी उस सरणी के संदर्भ शामिल हैं जिसे अद्यतन किया जा रहा है। मेरा जवाब हटाना :) –

+1

मुझे लगता है कि डिफ़ॉल्ट मान हैश के निर्माता में पारित सरणी का संदर्भ है। जब आप उस पर 'धक्का' देते हैं, तो आप प्रतिलिपि बनाने के बजाय सरणी को सीधे संशोधित कर रहे हैं। एक सरल उदाहरण के लिए: 'एच = हैश.न्यू (' हैलो '); एच ['कुछ'] << 'aaa'; h.default' रखता है 'helloaaa' –