通过ruby中的一个数组对数组的哈希进行排序

时间:2015-10-24 09:22:03

标签: arrays ruby sorting hash

在Ruby中,有一种简短而又甜蜜的方法可以按分数降序对数组的哈希值进行排序:

scored = {:id=>[1, 2, 3], :score=>[8.3, 5, 10]}

所以它看起来像这样?:

scored = {:id=>[3, 1, 2], :score=>[10, 8.3, 5]}

我找不到一个例子,我可以像这样在哈希中对数组进行排序?我可以用一些令人讨厌的代码做到这一点,但我觉得应该有1或2个衬垫来做它吗?

3 个答案:

答案 0 :(得分:3)

您可以使用sort_by

scored = {:id=>[1, 2, 3], :score=>[8.3, 5, 10]}

scored.tap do |s| 
  s[:id] = s[:id].sort_by.with_index{ |a, i| -s[:score][i] }
  s[:score] = s[:score].sort_by{ |a| -a }
end
#=> {:id=>[3, 1, 2], :score=>[10, 8.3, 5]}

答案 1 :(得分:2)

order = scored[:score].each_with_index.sort_by(&:first).map(&:last).reverse
  #=> [2,0,1]
scored.update(scored) { |_,a| a.values_at *order }
  #=> {:id=>[3, 1, 2], :score=>[10, 8.3, 5]}

如果scored不要变异,请将update替换为merge

有些观点:

  • 计算order使读者更容易理解正在发生的事情。
  • 第二行使用Hash#merge的形式,它使用一个块来确定合并的两个哈希中存在的键的值(这里是所有键)。这是修改哈希值的一种方便方法(通常),部分原因是返回了新的哈希值。
  • 我排序然后反转,而不是按否定值排序,以使方法更加粗糙。 (也就是说,作为值的数组元素可以来自任何实现<=>的类。)
  • 使用Ruby 2.2+,另一种按降序排序数组arr的方法是使用Enumerable#max_byarr.max_by(arr.size).to_a

第一行可以替换为:

arr = scored[:score]
order = arr.each_index.sort_by { |i| arr[i] }.reverse
  #=> [2,0,1]

答案 2 :(得分:1)

这是一种可能的解决方案。它有一个中间步骤,它使用scores对象的压缩版本,但产生正确的输出:

s = scored.values.inject(&:zip).sort_by(&:last).reverse
#=> [[3, 10], [1, 8.3], [2, 5]]

result = { id: s.map(&:first), score: s.map(&:last) }
#=> { :id => [3, 1, 2], :score => [10, 8.3, 5] }