6

假设我有一个像这样的哈希:

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

4

4 回答 4

12

我会这样做:

Hash[foo.sort_by { |k, v| v.join.length }]

我假设您不打算更改原始哈希值,只需重新排序即可。

于 2012-06-08T23:59:56.340 回答
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 并希望将结果转换回哈希,您可以这样做(感谢 Jörg W Mittag):

Hash[ foo.sort_by { |key, strings| strings.join.length } ]

...这与 d11wtq 的答案相同。

于 2012-06-08T23:43:47.477 回答
1
   foo.sort_by { |_,v| v.reduce(:+).size }
于 2012-06-08T23:42:53.870 回答
1

哈希在其概念中并不能确保键的顺序。但是在 Ruby 1.9 中,Hash 的键顺序被保存了。因此,如果您使用 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
于 2012-06-08T23:46:18.263 回答