对具有重复值的哈希数组进行排序

时间:2015-02-20 16:20:17

标签: ruby hash

我有以下哈希数组:

arr = [{:id=>1, :val=>30}, {:id=>2, :val=>30}, {:id=>1002, :val=>82}]

我需要:

  • :val
  • 的值对其进行排序
  • 如果多个哈希具有相同的值,则它们的相对位置应反映原始顺序或反转顺序,具体取决于按:val值排序是升序还是降序
像这样:

arr.sort_by_ascending_order.map{|x| x[:id]}
# => [1, 2, 1002] 
arr.sort_by_descending_order.map{|x| x[:id]}
# => [1002, 2, 1]

我无法保证第二个条件。例如,

arr.sort{|x,y| x[:val] <=> y[:val]}.map{|x| x[:id]}
# => [1, 2, 1002] 
arr.sort{|x,y| y[:val] <=> x[:val]}.map{|x| x[:id]}
# => [1002, 1, 2] 

有人知道如何解决它吗?

1 个答案:

答案 0 :(得分:4)

您可以提供一个数组:

arr = [{:id=>1, :val=>30}, {:id=>2, :val=>30}, {:id=>1002, :val=>82}]

arr.sort { |x, y| [x[:val], x[:id]] <=> [y[:val], y[:id]] }
#=> [{:id=>1, :val=>30}, {:id=>2, :val=>30}, {:id=>1002, :val=>82}]

arr.sort { |x, y| [y[:val], y[:id]] <=> [x[:val], x[:id]] }
#=> [{:id=>1002, :val=>82}, {:id=>2, :val=>30}, {:id=>1, :val=>30}]

首先按:val排序,然后按:id排序(详见Array#<=>)。

您也可以使用sort_by

arr.sort_by { |h| [h[:val], h[:id]] }
#=> [{:id=>1, :val=>30}, {:id=>2, :val=>30}, {:id=>1002, :val=>82}]

<强>更新

当然,这不仅限于哈希值。您可以使用元素索引(作为suggested by sawa)作为辅助排序条件来实现stable sort

arr.sort_by.with_index { |h, i| [h[:val], i] }
#=> [{:id=>1, :val=>30}, {:id=>2, :val=>30}, {:id=>1002, :val=>82}]
相关问题