Ruby 在另一个数组中按索引排序

Ruby 在另一个数组中按索引排序,ruby,sorting,Ruby,Sorting,如果我有一个对象数组,如: [{id: 1, name: 'Apple'}, {id: 2, name: 'Orange'}, {id: 3, name: 'Banana'}] 我有一个ID数组:[3,1,2] Ruby是否有一种简洁和/或有效的方法来按照第二个数组中的ID对数组进行排序,如: [{id: 3, name: 'Banana'}, {id: 1, name: 'Apple'}, {id: 2, name: 'Orange'}] 可以这样做: a1 = [{id:

如果我有一个对象数组,如:

[{id: 1, name: 'Apple'},
  {id: 2, name: 'Orange'},
  {id: 3, name: 'Banana'}]
我有一个ID数组:[3,1,2]

Ruby是否有一种简洁和/或有效的方法来按照第二个数组中的ID对数组进行排序,如:

[{id: 3, name: 'Banana'},
  {id: 1, name: 'Apple'},
  {id: 2, name: 'Orange'}]

可以这样做:

a1 = [{id: 1, name: 'Apple'}, {id: 2, name: 'Orange'}, {id: 3, name: 'Banana'}]
a2 = [3,1,2]

a1.sort_by{|h| a2.index(h[:id])}

可以这样做:

a1 = [{id: 1, name: 'Apple'}, {id: 2, name: 'Orange'}, {id: 3, name: 'Banana'}]
a2 = [3,1,2]

a1.sort_by{|h| a2.index(h[:id])}
其他两种方式:

一,

二,

基准

方法比较

测试数据

基准例程

结语

order_hashes2从未走出大门,对此我并不感到惊讶,但令我吃惊的是,构建散列,然后使用值_at提取值比@sawa的解决方案快得多。我预计后者大部分时间都在执行索引操作

读者挑战者:有很多其他的方法来解决这个问题。让我们看看你的建议,我将把它们添加到基准中

还有两种方式:

一,

二,

基准

方法比较

测试数据

基准例程

结语

order_hashes2从未走出大门,对此我并不感到惊讶,但令我吃惊的是,构建散列,然后使用值_at提取值比@sawa的解决方案快得多。我预计后者大部分时间都在执行索引操作


读者挑战者:有很多其他的方法来解决这个问题。让我们看看你的建议,我将把它们添加到基准中

@sawa:编辑只是为了改变风格?我喜欢它稀疏…@BorisStitnicky你编辑只是为了改变风格。我还原了你做的一些不必要的更改。请不要改变OP的风格,尤其是从一个好的风格到一个没有受过教育的人的风格。受过教育的人不会在括号、大括号或方括号内加空格。有行尾是好的。@BorisStitnicky继续说:有行尾或缩进是好的。如果这听起来很冒犯,我很抱歉。我不是特别针对你。“我知道很多程序员都这样做,我对此很恼火。”sawa,这不是受教育与否的问题。我读过很多风格手册,我更喜欢可读性而不是保存字符。我知道80个字符行上的字符空间是宝贵的,但当父母挤在一起时,我的大脑根本看不到。所以这是个人偏好或个人能力的问题。如果你能有效地阅读填鸭式英语,恭喜你。“我不会和你发动战争的。”鲍里斯·蒂尼基我不知道你说的对不对。这不是保存字符的问题。这是一个可读性问题。这些角色被设计成围绕着某个东西,当它们放在内容旁边时,中间没有空格,看起来很漂亮。此外,没有一本样式手册会告诉你在里面放空格。一个受过教育的人应该遵守这些规则。你和我都同意这应该是为了可读性/美观,但我们似乎有相反的感觉。@sawa:编辑只是为了改变风格?我喜欢它稀疏…@BorisStitnicky你编辑只是为了改变风格。我还原了你做的一些不必要的更改。请不要改变OP的风格,尤其是从一个好的风格到一个没有受过教育的人的风格。受过教育的人不会在括号、大括号或方括号内加空格。有行尾是好的。@BorisStitnicky继续说:有行尾或缩进是好的。如果这听起来很冒犯,我很抱歉。我不是特别针对你。“我知道很多程序员都这样做,我对此很恼火。”sawa,这不是受教育与否的问题。我读过很多风格手册,我更喜欢可读性而不是保存字符。我知道80个字符行上的字符空间是宝贵的,但当父母挤在一起时,我的大脑根本看不到。所以这是个人偏好或个人能力的问题。如果你能有效地阅读填鸭式英语,恭喜你。“我不会和你发动战争的。”鲍里斯·蒂尼基我不知道你说的对不对。这不是保存字符的问题。这是一个可读性问题。这些角色被设计成围绕着某个东西,当它们放在内容旁边时,中间没有空格,看起来很漂亮。此外,没有一本样式手册会告诉你在里面放空格。一个受过教育的人应该遵守这些规则。你和我都同意这应该是为了可读性/美观,但我们似乎有相反的感觉。
def order_hashes2(a,order)
  order.map { |i| a.find { |h| h[:id] == i } }
end

order_hashes2(a1,a2)
  #=> [{:id=>3, :name=>"Banana"},
  #    {:id=>1, :name=>"Apple"},
  #    {:id=>2, :name=>"Orange"}]
module Methods
  def sawa(a,order)
    a.sort_by{ |h| order.index(h[:id]) }
  end

  def order_hashes1(a,order)
    a.each_with_object({}) { |h,g| g.update({h[:id]=>h}) }.values_at(*order)
  end

  def order_hashes2(a,order)
    order.map { |i| a.find { |h| h[:id] == i } }
  end
end

include Methods
methods = Methods.instance_methods(false)
  #=> [:order_hashes1, :order_hashes2, :sawa]
def test_data(n)
  a1 = n.times.with_object([]) { |i,a| a << { id: i, name: 'Apple' } }.shuffle
  a2 = n.times.to_a.shuffle
  [a1, a2]
end
a1, a2 = test_data(1_000)
result = send(method.first, a1, a2)
puts methods[1..-1].all? { |m| result = send(m,a1,a2) }
  #=> true
require 'benchmark'

a1, a2 = test_data(20_000)

Benchmark.bm(methods.map { |m| m.to_s.size }.max) do |bm|
  methods.each do |m|
    bm.report m.to_s do
      send(m, a1, a2)
    end
  end
end    
                    user     system      total        real
order_hashes1   0.030000   0.000000   0.030000 (  0.033169)
order_hashes2  49.300000   0.110000  49.410000 ( 49.486159)
sawa            1.500000   0.000000   1.500000 (  1.499078)