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

这是对哈希进行排序并返回hash对象(而不是Array)的最佳方法吗?

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}
214474 次浏览

注意: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

但总的来说,谈论一个排序的哈希是没有意义的。在文档中,“按键或值遍历哈希的顺序似乎是任意的,通常不是插入顺序。”因此,以特定顺序向散列中插入键是没有用的。

如果你不想使用ruby 1.9.2或使用你自己的变通方法,ActiveSupport这样::OrderedHash是另一个选择。

我喜欢之前帖子中的解决方案。

我创建了一个迷你类,命名为class AlphabeticalHash。它还有一个名为ap的方法,该方法接受一个参数Hash作为输入:ap variable。类似于pp (pp variable)

但它将(试着)按字母顺序打印(它的键)。不知道是否有人想使用这个,它是可用的宝石,你可以这样安装:gem install alphabetical_hash

对我来说,这很简单。如果其他人需要更多的功能,让 我知道,我会把它包括到宝石

编辑:功劳归于彼得,他给了我这个想法。:)

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

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

不,它不是(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倍甚至更多

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

我一直使用sort_by。你需要用Hash[]包装#sort_by输出,使其输出散列,否则它输出数组的数组。或者,要实现这一点,你可以在元组数组上运行#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哈希的数字值?”中也有类似的问题。

在Ruby 2.1中,它很简单:

h.sort.to_h

我也遇到过同样的问题(我必须把我的设备按名字分类),我是这样解决的:

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

@equipments是我在模型上构建并返回到控制器上的哈希值。如果你调用.sort,它会根据它的键值对哈希进行排序。

通过关键排序哈希,在Ruby中返回哈希

使用解构和hash# 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 }

注意:& lt;Ruby 2.1

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

注:> Ruby 2.1

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

我借用Boris Stitnicky的灵感解决方案,将一个就地sort!方法修补到Hash中:

def sort!
keys.sort!.each { |k| store k, delete(k) }
self
end

你可以使用sort方法,然后用to_h方法将数组转换回哈希

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