किसी अन्य कुंजी के साथ हैश कुंजी को कैसे बदलें


191

मेरी एक शर्त है जहां, मुझे एक हैश मिलता है

  hash = {"_id"=>"4de7140772f8be03da000018", .....}

और मुझे यह हैश चाहिए

  hash = {"id"=>"4de7140772f8be03da000018", ......}

पुनश्च : मुझे नहीं पता है कि हैश में क्या हैं, वे यादृच्छिक हैं जो हर कुंजी के लिए "_" उपसर्ग के साथ आता है और मुझे कोई अंडरस्कोर नहीं चाहिए


यह आपकी मदद कर सकता है: stackoverflow.com/questions/4044451/...
जीर्णशीर्ण

उपयोगी प्रश्न के लिए +1
ashisrai_

@ a5 यह: मुझे खुशी है कि यह मदद की थी :)
मनीष दास

जवाबों:


710
hash[:new_key] = hash.delete :old_key

8
मुझे एक जोड़े को बचाया, प्यार करो!
निकोहवी

10
मुझे अक्सर "स्मार्ट" रूबी कोड पसंद नहीं है क्योंकि यह बताने के लिए कुछ समय लगता है कि यह वास्तव में क्या कर रहा है। आपका समाधान दूसरे हाथ में सरल और वर्णनात्मक है।
लुकास

3
यह वास्तव में स्वीकृत उत्तर होना चाहिए! आसान, साफ और सीधे मुद्दे पर!
गीगाबास

1
यह उत्तर सुरुचिपूर्ण है लेकिन यह वास्तव में प्रश्न का उत्तर नहीं देता है। पोस्ट में कहा गया है कि जिन कुंजियों को बदलने की आवश्यकता है वे अज्ञात हैं ... हम केवल यह जानते हैं कि वे एक अंडरस्कोर से शुरू करते हैं, हम नहीं जानते कि वास्तव में कुंजी क्या हैं।
Dsel

2
इसलिए यह एक नई कुंजी / मूल्य जोड़ी बनाता है जहां आप नई कुंजी निर्दिष्ट करते हैं और hash.delete :old_keyरिटर्न से मूल्य प्राप्त करते हैं और हटाएं पुरानी कुंजी का उपयोग करता है। वाह, मैं चाहता हूं कि यह कहीं टैटू बन जाए: -D धन्यवाद
बार्ट सी

136

रेल हैश के पास इसके लिए मानक विधि है:

hash.transform_keys{ |key| key.to_s.upcase }

http://api.rubyonrails.org/classes/Hash.html#method-i-transform_keys

UPD: रूबी 2.5 विधि


4
यह रेल विधि है, मानक नहीं। हालांकि अच्छा जवाब।
user2422869

1
इसके अलावा, यह विधि हैश कीज़ के साथ पुनरावर्ती रूप से काम नहीं कर सकती है।
सर्जियो बेलेवस्कीज

5
deep_transform_keys का उपयोग इसके लिए किया जा सकता है :) apidock.com/rails/v4.2.1//ash/deep_transform_keys
gayavat

1
अंत में! यह वही है जो मैंने खोजा था!
तिवारी

4
यह रूबी 2.5 के रूप में भाषा का एक मानक हिस्सा है: docs.ruby-lang.org/en/trunk/Hash.html#method-i-transform_keys
डेविड ग्रेसन

39

यदि सभी कुंजी तार हैं और उन सभी में अंडरस्कोर उपसर्ग है, तो आप इसके साथ हैश को पैच कर सकते हैं:

h.keys.each { |k| h[k[1, k.length - 1]] = h[k]; h.delete(k) }

k[1, k.length - 1]बिट के सभी पकड़ लेता है kपहले वर्ण को छोड़कर। यदि आप एक प्रति चाहते हैं, तो:

new_h = Hash[h.map { |k, v| [k[1, k.length - 1], v] }]

या

new_h = h.inject({ }) { |x, (k,v)| x[k[1, k.length - 1]] = v; x }

subयदि आप k[]एक विकल्प निकालने के लिए संकेतन पसंद नहीं करते हैं तो आप इसका उपयोग भी कर सकते हैं :

h.keys.each { |k| h[k.sub(/\A_/, '')] = h[k]; h.delete(k) }
Hash[h.map { |k, v| [k.sub(/\A_/, ''), v] }]
h.inject({ }) { |x, (k,v)| x[k.sub(/\A_/, '')] = v; x }

और, यदि केवल कुछ कुंजियों में अंडरस्कोर उपसर्ग है:

h.keys.each do |k|
  if(k[0,1] == '_')
    h[k[1, k.length - 1]] = h[k]
    h.delete(k)
  end
end

इसी तरह के संशोधन उपरोक्त सभी अन्य वेरिएंट में किए जा सकते हैं लेकिन ये दोनों:

Hash[h.map { |k, v| [k.sub(/\A_/, ''), v] }]
h.inject({ }) { |x, (k,v)| x[k.sub(/\A_/, '')] = v; x }

उन कुंजियों के साथ ठीक होना चाहिए जिनमें अतिरिक्त संशोधनों के बिना अंडरस्कोर उपसर्ग नहीं हैं।


आपके उत्तर ने काम किया लेकिन वार्ड के बाद मुझे कुछ इस तरह से हैश मिला
मनीष दास

3
{"_id" => "4de7140772f8be03da000018", "_type" => "वर्कस्टेशन", "create_at" = "2011-06-02T10: 24: 35 + 05: 45," input_header_ids "= []," line_id "=>" 4de7140472f8be03da000017 "," updated_at "=>" 2011-06-02T10: 24: 35 + 05: 45 "}
मनीष दास

2
{"id" => "4de7140772f8be03da000018", "टाइप" => "वर्कस्टेशन", "reated_at" = "" 2011-06-02T10: 24: 35 + 05: 45 "," nput_header_ids "= []," ine_id_id "=>" 4de7140472f8be03da000017 "," pdated_at "=>" 2011-06-02T10: 24: 35 + 05: 45 "}
मनीष दास

@Manish: मैंने कहा था "यदि सभी कुंजी तार हैं और उन सभी में अंडरस्कोर उपसर्ग है"। मैंने एक अपडेट में अंडरस्कोर प्रीफिक्स के बिना आपकी "कुंजियों के लिए एक उदाहरण दृष्टिकोण" शामिल किया।
म्यू बहुत छोटा है

2
@Manish: "k" "की" के लिए है, "v" "वैल्यू" के लिए है, "x" "मैं" नहीं जानता कि इसे क्या कहा जाए लेकिन मैं गणितज्ञ के रूप में प्रशिक्षित था इसलिए मैं इसे x कहता हूं।
म्यू बहुत छोटा है


11

यदि हम हैश में एक विशिष्ट कुंजी का नाम बदलना चाहते हैं, तो हम इसे निम्नानुसार कर सकते हैं:
मान लीजिए कि मेरा हैश है my_hash = {'test' => 'ruby hash demo'}
अब मैं 'परीक्षण' को 'संदेश' से बदलना चाहता हूं, फिर:
my_hash['message'] = my_hash.delete('test')


फिर आपका जवाब मेरी समस्या का समाधान कैसे है? अगर आपको लगता है कि यह मददगार था, तो आप सवाल के तहत टिप्पणी में जोड़ सकते हैं। मेरा प्रश्न एक कुंजी को दूसरी कुंजी के साथ बदलने का नहीं था, आपने जो समाधान दिया वह बहुत ही मूल हैश प्रॉपर्टी है। मेरे मामले में यह नहीं है: hash[:new_key] = has[:old_key]इसके बजाय, यह है: hash[:dynamic_key] = hash[:_dynamic_key]यह रेगेक्स पर स्पष्ट सवाल था और साधारण हैश की जगह नहीं।
मनीष दास

2
मैं एक Google खोज के माध्यम से इस पर आया और @ स्वप्निल का जवाब चाहता था। धन्यवाद
३ke

10
h.inject({}) { |m, (k,v)| m[k.sub(/^_/,'')] = v; m }

4
मुझे पसंद है कि आपने अंडरस्कोर को ठीक से फ़िल्टर करने के लिए एक रेगेक्स का उपयोग करने की कोशिश की, लेकिन आपको पता होना चाहिए कि माणिक में, जावास्क्रिप्ट और अन्य के विपरीत, / ^ / 'का अर्थ है स्ट्रिंग या लाइन की शुरुआत' और / $ / का अर्थ है 'अंत' स्ट्रिंग या लाइन '। यह संभावना नहीं है कि इस मामले में चाबियाँ उनके पास नई हैं, लेकिन आपको पता होना चाहिए कि रूबी में उन दो ऑपरेटरों का उपयोग करना न केवल त्रुटि प्रवण है, बल्कि इंजेक्शन के खिलाफ मान्यताओं में गलत उपयोग किए जाने पर बहुत खतरनाक है। स्पष्टीकरण के लिए यहां देखें । आशा है कि आप जागरूकता फैलाने से गुरेज नहीं करेंगे।
Jorn van de Beek


1

मैं आगे निकल गया और निम्नलिखित के साथ आया। इसके पीछे मेरी प्रेरणा एक साथ विलय / चपटे हैश में गुंजाइश संघर्षों से बचने के लिए हैश कीज़ के लिए अपील करना था।

उदाहरण

हैश क्लास बढ़ाओ

हेश उदाहरणों के लिए rekey विधि जोड़ता है।

# Adds additional methods to Hash
class ::Hash
  # Changes the keys on a hash
  # Takes a block that passes the current key
  # Whatever the block returns becomes the new key
  # If a hash is returned for the key it will merge the current hash 
  # with the returned hash from the block. This allows for nested rekeying.
  def rekey
    self.each_with_object({}) do |(key, value), previous|
      new_key = yield(key, value)
      if new_key.is_a?(Hash)
        previous.merge!(new_key)
      else
        previous[new_key] = value
      end
    end
  end
end

उदाहरण प्रस्तुत करें

my_feelings_about_icecreams = {
  vanilla: 'Delicious',
  chocolate: 'Too Chocolatey',
  strawberry: 'It Is Alright...'
}

my_feelings_about_icecreams.rekey { |key| "#{key}_icecream".to_sym }
# => {:vanilla_icecream=>"Delicious", :chocolate_icecream=>"Too Chocolatey", :strawberry_icecream=>"It Is Alright..."}

ट्रिम उदाहरण

{ _id: 1, ___something_: 'what?!' }.rekey do |key|
  trimmed = key.to_s.tr('_', '')
  trimmed.to_sym
end
# => {:id=>1, :something=>"what?!"}

एक "स्कोप" को समतल करना और लगाना

यदि आप एक हैश को फिर से पास करने के लिए पास करते हैं तो यह हैश को मर्ज कर देगा जो आपको संग्रह समतल करने की अनुमति देता है। यह हमें विलय के समय एक कुंजी को ओवरराइट करने से बचने के लिए हैश को सपाट करने पर हमारी कुंजी में गुंजाइश जोड़ने की अनुमति देता है।

people = {
  bob: {
    name: 'Bob',
    toys: [
      { what: 'car', color: 'red' },
      { what: 'ball', color: 'blue' }
    ]
  },
  tom: {
    name: 'Tom',
    toys: [
      { what: 'house', color: 'blue; da ba dee da ba die' },
      { what: 'nerf gun', color: 'metallic' }
    ]
  }
}

people.rekey do |person, person_info|
  person_info.rekey do |key|
    "#{person}_#{key}".to_sym
  end
end

# =>
# {
#   :bob_name=>"Bob",
#   :bob_toys=>[
#     {:what=>"car", :color=>"red"},
#     {:what=>"ball", :color=>"blue"}
#   ],
#   :tom_name=>"Tom",
#   :tom_toys=>[
#     {:what=>"house", :color=>"blue; da ba dee da ba die"},
#     {:what=>"nerf gun", :color=>"metallic"}
#   ]
# }

0

पिछले उत्तर काफी अच्छे हैं, लेकिन वे मूल डेटा को अपडेट कर सकते हैं। यदि आप मूल डेटा को प्रभावित नहीं करना चाहते हैं, तो आप मेरे कोड को आज़मा सकते हैं।

 newhash=hash.reject{|k| k=='_id'}.merge({id:hash['_id']})

पहले यह कुंजी '_id' को नजरअंदाज करेगा और फिर अद्यतन के साथ विलय करेगा।

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