Ruby:如何按特定键的给定顺序对哈希数组进行排序

3

我有一个哈希数组,其中id是哈希中的关键字之一。我想根据给定的ID值顺序对数组元素进行排序。

假设我的数组(大小=5)如下:

[{"id"=>1. ...}, {"id"=>4. ...}, {"id"=>9. ...}, {"id"=>2. ...}, {"id"=>7. ...}]

我希望对数组元素进行排序,按照它们的id顺序排列,顺序如下:
[1,3,5,7,9,2,4,6,8,10]

所以预期的结果是:
[{'id' => 1},{'id' => 7},{'id' => 9},{'id' => 2},{'id' => 4}]
5个回答

7
以下是任何自定义索引的解决方案:
def my_index x 
  # Custom code can be added here to handle items not in the index.
  # Currently an error will be raised if item is not part of the index.
  [1,3,5,7,9,2,4,6,8,10].index(x) 
end

my_collection = [{"id"=>1}, {"id"=>4}, {"id"=>9}, {"id"=>2}, {"id"=>7}]
p my_collection.sort_by{|x| my_index x['id'] } #=> [{"id"=>1}, {"id"=>7}, {"id"=>9}, {"id"=>2}, {"id"=>4}]

然后你可以以任何你想要的方式进行格式化,也许这样更美观:
my_index = [1,3,5,7,9,2,4,6,8,10]
my_collection.sort_by{|x| my_index.index x['id'] }

1
一般的排序说明。使用类的#sort_by方法:
[{'id' => 1},{'id'=>3},{'id'=>2}].sort_by {|x|x['id'] }
# => [{"id"=>1}, {"id"=>2}, {"id"=>3}]

或者使用 #values 方法作为回调函数:
[{'id' => 1},{'id'=>3},{'id'=>2}].sort_by(&:values)
# => [{"id"=>1}, {"id"=>2}, {"id"=>3}]

或者您可以使用更明显的版本,使用#sort方法:

[{'id' => 1},{'id'=>3},{'id'=>2}].sort {|x,y| x['id'] <=> y['id'] }
# => [{"id"=>1}, {"id"=>2}, {"id"=>3}]

对于您的情况,如果要按照扩展条件排序,请使用#%来区分偶数和奇数索引:
[{'id' => 1},{'id'=>4},{'id'=>9},{'id'=>2},{'id'=>7}].sort do |x,y|
    u = y['id'] % 2 <=> x['id'] % 2
    u == 0 && y['id'] <=> x['id'] || u 
end
# => [{"id"=>1}, {"id"=>7}, {"id"=>9}, {"id"=>2}, {"id"=>4}]

针对您的情况,要按扩展条件进行排序,请使用#%根据索引进行拆分,即使在索引数组中缺少id值也可以这样做。
index = [1,3,5,7,4,2,6,8,10] # swapped 2 and 4, 9 is absent

[{'id' => 1},{'id'=>4},{'id'=>9},{'id'=>2},{'id'=>7}].sort do |x,y|
   !index.rindex( x[ 'id' ] ) && 1 || index.rindex( x[ 'id' ] ) <=> index.rindex( y[ 'id' ] ) || -1 
end
# => [{"id"=>1}, {"id"=>7}, {"id"=>4}, {"id"=>2}, {"id"=>9}]

预期结果是 [{'id' => 1},{'id' => 7},{'id' => 9},{'id' => 2},{'id' => 4}] - nish
@Малъ 我喜欢简洁的解决方案。 - Roman Kiselenko
@МалъСкрылевъ 这在这种情况下(先奇数再偶数)可以工作,但是否有一般解决方案。我可能会遇到希望顺序是随机的情况。 - nish
@МалъСкрылевъ:例如,所需顺序为[1,5,3,2,8,9,7,6,4]。 - nish
所以,请看一下我的答案,我已经回答了这个问题。 - hirolau
@hirolau:是的,我尝试了你的解决方案,它起作用了。抱歉我忘记接受答案。感谢你的帮助 :) - nish

1
我会像这样根据值来映射哈希表:

a = [{"id"=>1}, {"id"=>4}, {"id"=>9}, {"id"=>2}, {"id"=>7}]

[1,3,5,7,9,2,4,6,8,10].map{|x| a[a.index({"id" => x})] }.compact

#=> [{"id"=>1}, {"id"=>7}, {"id"=>9}, {"id"=>2}, {"id"=>4}]

0
a= [{"id"=>1}, {"id"=>4}, {"id"=>9}, {"id"=>2}, {"id"=>7}]
b=[1,3,5,7,9,2,4,6,8,10]
a.sort_by{|x| b.index (x['id'])}

0

为什么不直接使用sort呢?

def doit(arr, order)
  arr.sort { |h1,h2| order.index(h1['id']) <=> order.index(h2['id']) }
end

order = [1,3,5,7,9,2,4,6,8,10]
arr = [{'id' => 1}, {'id' => 4}, {'id' => 9}, {'id' => 2}, {'id' => 7}]     

doit(arr, order)
  #=> [{'id' => 1}, {'id' => 7}, {'id' => 9}, {'id' => 2}, {'id' => 4}]     

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接