ハッシュの要素を逆にして、同じ値とキーを維持しながら、ハッシュの順序を逆にするにはどうすればよいですか。
そのようです:
{ "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
そしてそれを次のように変換します:
{ "1" => "spider", "lala" => "54", "10" => "cool", "4" => "happiness" }
あるいは、each
ループを最初にではなく、ハッシュの最後の要素から始めて、逆方向に実行することもできますか?
ハッシュを配列に変換し、それを逆にしてから、ハッシュに戻すことができます。
reversed_h = Hash[h.to_a.reverse]
Hash#to_a
は配列の配列を提供します。内部配列は単純な[key,value]
ペアであり、次に Array#reverse
を使用してその配列を逆にします。および Hash[]
は、[key,value]
のペアをハッシュに変換します。
Ruby 2.1には Array#to_h
メソッドが追加されているので、次のように言うことができます。
reversed_h = h.to_a.reverse.to_h
Ruby 2.1+では、 reverse_each
および to_h
:
{foo: 1, bar: 2}.reverse_each.to_h
#=> {:bar=>2, :foo=>1}
hash = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
reversed_hash = Hash[hash.to_a.reverse]
h = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
p Hash[h.reverse_each.map{|e| e}]
#=> {"1"=>"spider", "lala"=>"54", "10"=>"cool", "4"=>"happiness"}
しかし、これは悪い味を残します(他の答えと同じように、これはこのようにうまく機能します)。これを行う必要がある場合は、ハッシュが最良の選択ではなかった可能性があります。
reversed_h = Hash[h.to_a.collect(&:reverse)]
純粋なRubyでは、hash.map(&:reverse).to_h
またはhash.reverse_each.to_h
で実行できます。
Railsでは、hash.invert
で実行できます。
必要なら:
hash = {:a => :x, :b => :y, :c => :y, :d => :z}
に:
{:x => [:a], :y => [:b, c], :z => [:d] }
できる:
h={};hash.to_a.each{|e|h[e[1]]||=[];h[e[1]]<<e[0]};h
または、reduce
およびmerge
を使用して、アイテムを新しいハッシュの前に追加できます。
hash = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
hash.reduce({}){ |memo, object| Hash[*object].merge(memo) }
しかし、それはクレイジーです:D
Ruby 1.8.7 では、ハッシュ内の要素の順序は私たちの制御下にないことが文書化されているため、上記の方法はどれも機能しません。 Ruby 1.9. では、物事は機能し、他の回答が依存する方法で文書化されています。
$ irb1.8 h = {"4" => "幸福"、 "10" => "クール"、 "lala" => "54"、 "1" => " spider "} Hash [h.to_a()。reverse()] => {" lala "=>" 54 "、" 1 "=>" spider "、" 10 "= > "cool"、 "4" => "happiness"} quit $ irb1.9.1 h = {"4" => "happiness"、 "10" = > "cool"、 "lala" => "54"、 "1" => "spider"} Hash [h.to_a()。reverse()] => {"1 "=>"スパイダー "、" lala "=>" 54 "、" 10 "=>"クール "、" 4 "=>"幸福 "}
Ruby 1.8.7の方法は非常にしっかりと根付いていたので、しばらくの間、質問を誤解していました。- Hash#invert :範囲をドメインにマップするようにハッシュを変換します。このメソッドは重複を破棄します。LuísRamalhoは a method を提供しますが、そうではありませんが、少し不格好です。これは少し短いです:
$ irb def invertWithDuplicates(original) reverse = Hash.new(){| hash、key |ハッシュ[キー] = []; } original.each_pair(){| key、value | reverse [value] .Push(key); } return reverse end h = {"4" => "happiness"、 "10" => "cool"、 "lala" => "54"、 " 1 "=>" cool "} invertWithDuplicates(h) => {" happiness "=> [" 4 "]、" cool "=> [" 1 "、" 10 "] 、 "54" => ["lala"]}
OPの意図したトピックから離れて申し訳ありませんが、これは投稿のタイトル「Reverse a hash in Ruby」に適合していると私は思います。