मैं एक हाश में कुंजियों और मूल्यों को कैसे स्वैप करूं?
मेरे पास निम्नलिखित हैश है:
{:a=>:one, :b=>:two, :c=>:three}
में बदलना चाहता हूँ:
{:one=>:a, :two=>:b, :three=>:c}
प्रयोग map
थकाऊ लगता है। क्या कोई छोटा उपाय है?
मैं एक हाश में कुंजियों और मूल्यों को कैसे स्वैप करूं?
मेरे पास निम्नलिखित हैश है:
{:a=>:one, :b=>:two, :c=>:three}
में बदलना चाहता हूँ:
{:one=>:a, :two=>:b, :three=>:c}
प्रयोग map
थकाऊ लगता है। क्या कोई छोटा उपाय है?
जवाबों:
रूबी के पास हैश के लिए एक सहायक विधि है जो आपको एक हैश का इलाज करने देती है जैसे कि यह उलटा था (संक्षेप में, आपको मूल्यों के माध्यम से कुंजी तक पहुंचने की अनुमति देकर):
{a: 1, b: 2, c: 3}.key(1)
=> :a
यदि आप उल्टे हैश रखना चाहते हैं, तो हैश # इनवर्टर को अधिकांश स्थितियों के लिए काम करना चाहिए:
{a: 1, b: 2, c: 3}.invert
=> {1=>:a, 2=>:b, 3=>:c}
परंतु...
यदि आपके पास डुप्लिकेट मान हैं, तो invert
अपने मूल्यों की अंतिम घटना को छोड़ देंगे , लेकिन (क्योंकि यह निर्गमन के दौरान उस कुंजी के लिए नए मूल्य को बदलना होगा)। इसी तरह, key
केवल पहला मैच लौटाएंगे:
{a: 1, b: 2, c: 2}.key(2)
=> :b
{a: 1, b: 2, c: 2}.invert
=> {1=>:a, 2=>:c}
इसलिए, यदि आपके मूल्य अद्वितीय हैं, तो आप उपयोग कर सकते हैं Hash#invert
। यदि नहीं, तो आप सभी मानों को एक सरणी के रूप में रख सकते हैं, जैसे:
class Hash
# like invert but not lossy
# {"one"=>1,"two"=>2, "1"=>1, "2"=>2}.inverse => {1=>["one", "1"], 2=>["two", "2"]}
def safe_invert
each_with_object({}) do |(key,value),out|
out[value] ||= []
out[value] << key
end
end
end
नोट: परीक्षणों वाला यह कोड अब GitHub पर है ।
या:
class Hash
def safe_invert
self.each_with_object({}){|(k,v),o|(o[v]||=[])<<k}
end
end
each_with_object({}){ |i,o|k,v = *i; o[v] ||=[]; o[v] << k}
... अच्छा हो जाता है
तुम शर्त लगा लो एक है! रूबी में चीजों को करने का हमेशा एक छोटा तरीका है!
यह बहुत आसान है, बस उपयोग करें Hash#invert
:
{a: :one, b: :two, c: :three}.invert
=> {:one=>:a, :two=>:b, :three=>:c}
Et voilà!
files = {
'Input.txt' => 'Randy',
'Code.py' => 'Stan',
'Output.txt' => 'Randy'
}
h = Hash.new{|h,k| h[k] = []} # Create hash that defaults unknown keys to empty an empty list
files.map {|k,v| h[v]<< k} #append each key to the list at a known value
puts h
यह डुप्लिकेट मानों को भी संभाल लेगा।
# this doesn't looks quite as elegant as the other solutions here,
# but if you call inverse twice, it will preserve the elements of the original hash
# true inversion of Ruby Hash / preserves all elements in original hash
# e.g. hash.inverse.inverse ~ h
class Hash
def inverse
i = Hash.new
self.each_pair{ |k,v|
if (v.class == Array)
v.each{ |x|
i[x] = i.has_key?(x) ? [k,i[x]].flatten : k
}
else
i[v] = i.has_key?(v) ? [k,i[v]].flatten : k
end
}
return i
end
end
Hash#inverse
आपको देता है:
h = {a: 1, b: 2, c: 2}
h.inverse
=> {1=>:a, 2=>[:c, :b]}
h.inverse.inverse
=> {:a=>1, :c=>2, :b=>2} # order might not be preserved
h.inverse.inverse == h
=> true # true-ish because order might change
जबकि अंतर्निहित invert
विधि अभी टूटी हुई है:
h.invert
=> {1=>:a, 2=>:c} # FAIL
h.invert.invert == h
=> false # FAIL
सरणी का उपयोग करना
input = {:key1=>"value1", :key2=>"value2", :key3=>"value3", :key4=>"value4", :key5=>"value5"}
output = Hash[input.to_a.map{|m| m.reverse}]
हैश का उपयोग करना
input = {:key1=>"value1", :key2=>"value2", :key3=>"value3", :key4=>"value4", :key5=>"value5"}
output = input.invert
यदि आपके पास एक हैश है जहाँ कुंजियाँ अद्वितीय हैं, तो आप हैश # इनवर्ट का उपयोग कर सकते हैं :
> {a: 1, b: 2, c: 3}.invert
=> {1=>:a, 2=>:b, 3=>:c}
यदि आपके पास गैर-विशिष्ट कुंजियाँ हैं, तो यह काम नहीं करेगा, हालाँकि, जहाँ केवल अंतिम कुंजियाँ देखी जाएँगी:
> {a: 1, b: 2, c: 3, d: 3, e: 2, f: 1}.invert
=> {1=>:f, 2=>:e, 3=>:d}
यदि आपके पास गैर विशिष्ट कुंजियों वाला हैश है, तो आप ऐसा कर सकते हैं:
> hash={a: 1, b: 2, c: 3, d: 3, e: 2, f: 1}
> hash.each_with_object(Hash.new { |h,k| h[k]=[] }) {|(k,v), h|
h[v] << k
}
=> {1=>[:a, :f], 2=>[:b, :e], 3=>[:c, :d]}
यदि हैश के मूल्य पहले से ही सरणियाँ हैं, तो आप यह कर सकते हैं:
> hash={ "A" => [14, 15, 16], "B" => [17, 15], "C" => [35, 15] }
> hash.each_with_object(Hash.new { |h,k| h[k]=[] }) {|(k,v), h|
v.map {|t| h[t] << k}
}
=> {14=>["A"], 15=>["A", "B", "C"], 16=>["A"], 17=>["B"], 35=>["C"]}
each_with_object
से अधिक समझ में आता हैinject
।