web-dev-qa-db-ja.com

ハッシュをキーでソートし、ハッシュをRubyに返す

これがハッシュをソートして(Arrayではなく)Hashオブジェクトを返す最善の方法ですか?

h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
# => {"a"=>1, "c"=>3, "b"=>2, "d"=>4}

Hash[h.sort]
# => {"a"=>1, "b"=>2, "c"=>3, "d"=>4}
243
Vincent

Ruby 2.1ではそれは簡単です:

h.sort.to_h
202
Mark Thomas

注:Ruby> = 1.9.2には順序を保存するハッシュがあります。挿入される順序キーは列挙された順序になります。以下は、旧バージョンまたは下位互換コードに適用されます。

ソートハッシュの概念はありません。いいえ、あなたがしていることは正しくありません。

表示用にソートしたい場合は、文字列を返します。

"{" + h.sort.map{|k,v| "#{k.inspect}=>#{v.inspect}"}.join(", ") + "}"

または、キーを順番に並べたい場合は、

h.keys.sort

あるいは、要素に順番にアクセスしたい場合は、

h.sort.map do |key,value|
  # keys will arrive in order to this block, with their associated value.
end

しかし要約すると、ソートされたハッシュについて話すことは意味がありません。 " docs "より、キーまたは値でハッシュをたどる順序は任意のように思われますが、一般的には挿入順序には含まれません。 "そのため、ハッシュに特定の順序でキーを挿入しても意味がありません。

80
Peter

私はいつもsort_byを使っています。ハッシュを出力するには、#sort_by出力をHash[]でラップする必要があります。それ以外の場合は、配列の配列が出力されます。あるいは、これを実現するために、タプルの配列に対して#to_hメソッドを実行して、それらをk=>v構造体(ハッシュ)に変換することもできます。

hsh ={"a" => 1000, "b" => 10, "c" => 200000}
Hash[hsh.sort_by{|k,v| v}] #or hsh.sort_by{|k,v| v}.to_h

Ruby Hashを数値でソートするにはどうすればいいのですか? 」にも同様の質問があります。

63
boulder_ruby

いいえ、違います(Ruby 1.9.x)

require 'benchmark'

h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
many = 100_000

Benchmark.bm do |b|
  GC.start

  b.report("hash sort") do
    many.times do
      Hash[h.sort]
    end
  end

  GC.start

  b.report("keys sort") do
    many.times do
      nh = {}
      h.keys.sort.each do |k|
        nh[k] = h[k]
      end
    end
  end
end

       user     system      total        real
hash sort  0.400000   0.000000   0.400000 (  0.405588)
keys sort  0.250000   0.010000   0.260000 (  0.260303)

大きなハッシュの場合、差は最大10倍以上になります。

13
fl00r

Hash[h.sort]もっと多くの可能性を望んでいるのなら、元のハッシュを並べ替えてその場で修正することができます。

h.keys.sort.each { |k| h[k] = h.delete k }
12
Boris Stitnicky

ActiveSupport :: OrderedHash Ruby 1.9.2を使用したくない場合や、独自の回避策を実行したくない場合は、別の方法があります。

6
eremite

ハッシュをkeyでソートし、ハッシュをRubyに返す

デストラクチャリングとハッシュ#sortを使う

hash.sort { |(ak, _), (bk, _)| ak <=> bk }.to_h

列挙可能#sort_by

hash.sort_by { |k, v| k }.to_h

デフォルトの振る舞いでハッシュ#ソート

h = { "b" => 2, "c" => 1, "a" => 3  }
h.sort         # e.g. ["a", 20] <=> ["b", 30]
hash.sort.to_h #=> { "a" => 3, "b" => 2, "c" => 1 }

注:<Ruby 2.1

array = [["key", "value"]] 
hash  = Hash[array]
hash #=> {"key"=>"value"}

注:> Ruby 2.1

[["key", "value"]].to_h #=> {"key"=>"value"}
4
Moriarty

私は同じ問題を抱えていた(私は自分の装備をそれらの名前で分類しなければならなかった)そして私はこのようにして解決した:

<% @equipments.sort.each do |name, quantity| %>
...
<% end %>

@equipmentsは、モデルに基づいて構築してコントローラに返すハッシュです。 .sortを呼び出すと、キー値に基づいてハッシュがソートされます。

0
@ordered = {}
@unordered.keys.sort.each do |key|
  @ordered[key] = @unordered[key]
end
0
beornborn