按键排序哈希,在Ruby中返回哈希

Vin*_*ent 249 ruby sorting hashmap

这是排序哈希并返回哈希对象(而不是数组)的最佳方法:

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}
Run Code Online (Sandbox Code Playgroud)

Mar*_*mas 210

在Ruby 2.1中很简单:

h.sort.to_h
Run Code Online (Sandbox Code Playgroud)


Pet*_*ter 80

注意:Ruby> = 1.9.2有一个保持顺序的哈希:插入的顺序键将是它们被枚举的顺序.以下内容适用于旧版本或向后兼容代码.

没有排序哈希的概念.所以不,你正在做的事情是不对的.

如果要对其进行排序以显示,请返回一个字符串:

"{" + h.sort.map{|k,v| "#{k.inspect}=>#{v.inspect}"}.join(", ") + "}"
Run Code Online (Sandbox Code Playgroud)

或者,如果您想要按键顺序:

h.keys.sort
Run Code Online (Sandbox Code Playgroud)

或者,如果要按顺序访问元素:

h.sort.map do |key,value|
  # keys will arrive in order to this block, with their associated value.
end
Run Code Online (Sandbox Code Playgroud)

但总的来说,谈论排序的哈希是没有意义的.从文档中,"通过键或值遍历散列的顺序可能看起来是任意的,并且通常不会处于插入顺序中." 因此,按特定顺序将密钥插入哈希将无济于事.

  • 从1.9.2开始,将保留哈希插入顺序.见http://redmine.ruby-lang.org/issues/show/994 (26认同)
  • 如果没有回答OP问题的两个部分之一,这个答案如何得到20 + 1?"1)那个(OP示例)是排序哈希的最佳方法,2)并返回哈希对象"?我不羡慕+ 1's :)只是在读完答案之后,我仍然留下原始问题.此外,如果重点是没有排序哈希这样的东西看看这个问题的选择答案的评论http://stackoverflow.com/questions/489139/ruby-1-8-hashsort-not-return-hash - 丁阵列更好的方式 - 待办事项,这 (5认同)
  • "将保留启动1.9.2哈希插入顺序.",它很甜蜜. (4认同)
  • 我的第一个评论(感觉很有趣):例如,依赖于哈希排序会对早于1.9.2的Ruby版本进行静默和不可预测的破坏. (2认同)

bou*_*uby 63

我一直都在用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
Run Code Online (Sandbox Code Playgroud)

" 如何按数值排序Ruby Hash? "中有类似的问题.

  • 在散列上使用`sort_by`将返回一个数组.您需要再次将其映射为哈希.`散列[hsh.sort_by {| K,V | V}]` (8认同)
  • 对,排序是​​值:`hsh.sort_by(&:last).to_h => {"b"=> 10,"a"=> 1000,"c"=> 200000}`. (3认同)
  • 请注意,调用 `to_h` 仅在 Ruby 2.1.0+ 中受支持 (2认同)

fl0*_*00r 13

不,它不是(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)
Run Code Online (Sandbox Code Playgroud)

对于大哈希,差异将增长到10倍甚至更多


Bor*_*cky 12

你在OP中给出了自己最好的答案:Hash[h.sort]如果你渴望更多的可能性,这里就是对原始哈希进行原位修改以使其排序:

h.keys.sort.each { |k| h[k] = h.delete k }
Run Code Online (Sandbox Code Playgroud)


ere*_*ite 6

如果您不想使用ruby 1.9.2或推出自己的解决方法,ActiveSupport :: OrderedHash是另一种选择.

  • 我修正了指向谷歌的链接,以防一些历史学家想要研究过去如何做到这一点.但现在任何人都应该使用更新版本的Ruby. (3认同)

Mor*_*rty 5

按键对哈希排序,在Ruby中返回哈希

使用解构和Hash#sort

hash.sort { |(ak, _), (bk, _)| ak <=> bk }.to_h
Run Code Online (Sandbox Code Playgroud)

Enumerable#sort_by

hash.sort_by { |k, v| k }.to_h
Run Code Online (Sandbox Code Playgroud)

Hash#sort具有默认行为

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 }
Run Code Online (Sandbox Code Playgroud)

注意:<Ruby 2.1

array = [["key", "value"]] 
hash  = Hash[array]
hash #=> {"key"=>"value"}
Run Code Online (Sandbox Code Playgroud)

注意:> Ruby 2.1

[["key", "value"]].to_h #=> {"key"=>"value"}
Run Code Online (Sandbox Code Playgroud)

  • 如果不使用“v”,您应该在前面加上下划线“hash.sort_by { |k, _v|” k }.to_h` (3认同)