web-dev-qa-db-ja.com

Ruby

ハッシュの要素を逆にして、同じ値とキーを維持しながら、ハッシュの順序を逆にするにはどうすればよいですか。

そのようです:

{ "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }

そしてそれを次のように変換します:

{ "1" => "spider", "lala" => "54", "10" => "cool", "4" => "happiness" }

あるいは、eachループを最初にではなく、ハッシュの最後の要素から始めて、逆方向に実行することもできますか?

31
slyv

ハッシュを配列に変換し、それを逆にしてから、ハッシュに戻すことができます。

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
62
mu is too short

Ruby 2.1+では、 reverse_each および to_h

{foo: 1, bar: 2}.reverse_each.to_h
#=> {:bar=>2, :foo=>1}
6
Stefan
hash = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
reversed_hash = Hash[hash.to_a.reverse]
4
aromero
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"}

しかし、これは悪い味を残します(他の答えと同じように、これはこのようにうまく機能します)。これを行う必要がある場合は、ハッシュが最良の選択ではなかった可能性があります。

4
steenslag
reversed_h = Hash[h.to_a.collect(&:reverse)]
2
Minqi Pan

純粋なRubyでは、hash.map(&:reverse).to_hまたはhash.reverse_each.to_hで実行できます。

Railsでは、hash.invertで実行できます。

1
khaled_gomaa

必要なら:

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
0
dmitryck

または、reduceおよびmergeを使用して、アイテムを新しいハッシュの前に追加できます。

hash = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
hash.reduce({}){ |memo, object| Hash[*object].merge(memo) }

しかし、それはクレイジーです:D

0

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」に適合していると私は思います。

0
Martin Dorey