मैं एक हैश में हर मूल्य को बदलना चाहता हूं ताकि मूल्य से पहले और बाद में '%' को जोड़ा जा सके
{ :a=>'a' , :b=>'b' }
को बदलना होगा
{ :a=>'%a%' , :b=>'%b%' }
ऐसा करने का सबसे अच्छा तरीका क्या है?
मैं एक हैश में हर मूल्य को बदलना चाहता हूं ताकि मूल्य से पहले और बाद में '%' को जोड़ा जा सके
{ :a=>'a' , :b=>'b' }
को बदलना होगा
{ :a=>'%a%' , :b=>'%b%' }
ऐसा करने का सबसे अच्छा तरीका क्या है?
जवाबों:
यदि आप चाहते हैं कि वास्तविक स्ट्रिंग्स स्वयं स्थान पर उत्परिवर्तित करें (संभवतः और समान रूप से उसी स्ट्रिंग ऑब्जेक्ट के अन्य संदर्भों को प्रभावित कर रहे हैं):
# Two ways to achieve the same result (any Ruby version)
my_hash.each{ |_,str| str.gsub! /^|$/, '%' }
my_hash.each{ |_,str| str.replace "%#{str}%" }
यदि आप हैश को जगह में बदलना चाहते हैं, लेकिन आप स्ट्रिंग्स को प्रभावित नहीं करना चाहते हैं (आप चाहते हैं कि इसे नए स्ट्रिंग्स मिलें):
# Two ways to achieve the same result (any Ruby version)
my_hash.each{ |key,str| my_hash[key] = "%#{str}%" }
my_hash.inject(my_hash){ |h,(k,str)| h[k]="%#{str}%"; h }
यदि आप एक नया हैश चाहते हैं:
# Ruby 1.8.6+
new_hash = Hash[*my_hash.map{|k,str| [k,"%#{str}%"] }.flatten]
# Ruby 1.8.7+
new_hash = Hash[my_hash.map{|k,str| [k,"%#{str}%"] } ]
Hash.[]
सरणी जोड़े की एक श्रृंखला को स्वीकार नहीं करता है, इसके लिए प्रत्यक्ष तर्क की एक समान संख्या की आवश्यकता होती है (इसलिए सामने की तरफ)।
Hash#each
ब्लॉक की कुंजी और मान दोनों देता है। इस मामले में, मुझे चाबी की परवाह नहीं थी, और इसलिए मैंने इसे कुछ भी उपयोगी नहीं बताया। परिवर्तनीय नाम एक अंडरस्कोर के साथ शुरू हो सकते हैं, और वास्तव में सिर्फ एक अंडरस्कोर हो सकते हैं । ऐसा करने का कोई प्रदर्शन लाभ नहीं है, यह सिर्फ एक सूक्ष्म स्व-दस्तावेज नोट है जो मैं उस पहले ब्लॉक मूल्य के साथ कुछ नहीं कर रहा हूं।
my_hash.inject(my_hash){ |h,(k,str)| h[k]="%#{str}%"; h }
, ब्लॉक से हैश लौटना है
रूबी 2.1 और उच्चतर में आप कर सकते हैं
{ a: 'a', b: 'b' }.map { |k, str| [k, "%#{str}%"] }.to_h
#transform_values!
2.4+ का उपयोग करते हैं, तो sschmeck ( stackoverflow.com/a/41508214/6451879 ) द्वारा बताया गया उपयोग करना और भी आसान है ।
रूबी 2.4 ने विधि पेश की Hash#transform_values!
, जिसका आप उपयोग कर सकते हैं।
{ :a=>'a' , :b=>'b' }.transform_values! { |v| "%#{v}%" }
# => {:a=>"%a%", :b=>"%b%"}
Hash#transform_values
(धमाके के बिना) भी है, जो रिसीवर को संशोधित नहीं करता है। अन्यथा एक महान जवाब, धन्यवाद!
हश के मूल्यों को संशोधित करने का सबसे अच्छा तरीका है
hash.update(hash){ |_,v| "%#{v}%" }
कम कोड और स्पष्ट इरादा। तेजी से भी क्योंकि कोई भी नई वस्तुओं को उन मूल्यों से परे आवंटित नहीं किया जाता है जिन्हें बदलना होगा।
gsub!
।
update
इस इरादे से बेहतर है merge!
। मुझे लगता है कि यह सबसे अच्छा जवाब है।
k
, तो _
इसके बजाय उपयोग करें ।
एक और अधिक पठनीय एक, map
यह एकल-तत्व हैश की एक सरणी के reduce
साथ और वह हैmerge
the_hash.map{ |key,value| {key => "%#{value}%"} }.reduce(:merge)
Hash[the_hash.map { |key,value| [key, "%#{value}%"] }]
Array
(के लिए map
) फिर ए Hash
। फिर, कम किए गए ऑपरेशन के प्रत्येक चरण "मेमो" की नकल करेंगे Hash
और इसमें नए कुंजी-मूल्य जोड़े को जोड़ेंगे। कम से कम उपयोग पर :merge!
में reduce
अंतिम संशोधित करने के लिए Hash
जगह में। और अंत में, आप मौजूदा ऑब्जेक्ट के मूल्यों को संशोधित नहीं कर रहे हैं, बल्कि एक नई वस्तु का निर्माण कर रहे हैं, जो कि सवाल नहीं पूछा गया है।
nil
यदि the_hash
रिक्त है
इस कार्य के लिए एक नया 'रेल मार्ग' है :) http://api.rubyonrails.org/classes/Hash.html#method-i-transform_values
Hash#transform_values
। यह अब से जाने का रास्ता होना चाहिए।
एक तरीका जो मूल-प्रभाव का परिचय नहीं देता है:
h = {:a => 'a', :b => 'b'}
h2 = Hash[h.map {|k,v| [k, '%' + v + '%']}]
हैश # मैप भी एक दिलचस्प रीड हो सकता है क्योंकि यह बताता है कि Hash.map
हैश क्यों नहीं लौटता (यही कारण है कि [key,value]
जोड़े का परिणामी सरणी एक नए हैश में परिवर्तित हो जाता है) और उसी सामान्य पैटर्न के लिए वैकल्पिक दृष्टिकोण प्रदान करता है।
खुश कोडिंग।
[अस्वीकरण: मुझे यकीन नहीं है कि अगर Hash.map
शब्दार्थ रूबी २.x में बदल जाए]
Hash.map
शब्दार्थ रूबी 2.x में बदल जाता है?
my_hash.each do |key, value|
my_hash[key] = "%#{value}%"
end
each_with_object
रूबी 1.9 (आईआईआरसी) में है जो सीधे नाम तक पहुंचने की आवश्यकता से बचता है और Map#merge
काम भी कर सकता है। सुनिश्चित नहीं है कि जटिल विवरण कैसे भिन्न हैं।
RSpec के साथ इस तरह परीक्षण करने के बाद:
describe Hash do
describe :map_values do
it 'should map the values' do
expect({:a => 2, :b => 3}.map_values { |x| x ** 2 }).to eq({:a => 4, :b => 9})
end
end
end
आप हश # map_values को निम्नानुसार लागू कर सकते हैं:
class Hash
def map_values
Hash[map { |k, v| [k, yield(v)] }]
end
end
फ़ंक्शन का उपयोग इस तरह किया जा सकता है:
{:a=>'a' , :b=>'b'}.map_values { |v| "%#{v}%" }
# {:a=>"%a%", :b=>"%b%"}
यदि आप जिज्ञासु हैं कि कौन सा विस्थापित संस्करण सबसे तेज़ है तो यह है:
Calculating -------------------------------------
inplace transform_values! 1.265k (± 0.7%) i/s - 6.426k in 5.080305s
inplace update 1.300k (± 2.7%) i/s - 6.579k in 5.065925s
inplace map reduce 281.367 (± 1.1%) i/s - 1.431k in 5.086477s
inplace merge! 1.305k (± 0.4%) i/s - 6.630k in 5.080751s
inplace each 1.073k (± 0.7%) i/s - 5.457k in 5.084044s
inplace inject 697.178 (± 0.9%) i/s - 3.519k in 5.047857s