说我有一个类似的哈希:
foo = {
:bar => ['r', 'baz'], # has a total str length of 4 characters inside of the array
:baz => ['words', 'etc', 'long words'] # has a total str length of 18 characters inside of the array,
:blah => ['at'] # has a total str length of 2 characters inside of the array
# etc...
}
我如何按照数组中包含的项的总字符串长度对此哈希进行排序?在这种情况下,生成的哈希顺序应为::blah, :bar, :baz
答案 0 :(得分:12)
我只是这样做:
Hash[foo.sort_by { |k, v| v.join.length }]
我假设您不打算更改原始哈希值,只需重新排序。
答案 1 :(得分:3)
传统上,散列不是有序的,因此不可排序。 Ruby 1.9哈希是有序的,但该语言没有提供重新排序元素的简单方法。就像在1.8中一样,对哈希进行排序会返回一对数组:
{ c:3, a:1, b:2 }.sort => [ [:a,1], [:b,2], [:c,3] ]
(实际上,1.8会爆炸,因为符号在1.8中不具有可比性,但没关系。)
但是只要您对配对列表没有问题,就可以按照您喜欢的任何方式对哈希(或数组)进行排序。只需使用sort_by并传递一个提取排序键的块,或者使用sort来进行比较:
foo.sort_by { |key, strings| strings.join.length }
或者,如果你想要最长的那个:
foo.sort_by { |key, strings| -strings.join.length }
然后,如果你使用的是1.9并希望将结果变回Hash,那么你可以这样做(感谢JörgWMittag):
Hash[ foo.sort_by { |key, strings| strings.join.length } ]
...这与d11wtq的答案相同。
答案 2 :(得分:1)
foo.sort_by { |_,v| v.reduce(:+).size }
答案 3 :(得分:1)
哈希不保证其概念中键的顺序。但是在Ruby 1.9中,Hash's key order is saved。因此,如果使用1.9,则可以在其他答案中使用代码。
但我不想建议依赖此行为,因为它是隐式行为,我害怕未来的变化。相反,使用方法以字符串长度的总和的顺序产生哈希条目。
def each_by_length(hash)
hash = hash.sort_by { |_, strs| strs.map(&:length).inject(0, &:+) }
hash.each do |k, v|
yield k, v
end
end