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

时间:2014-09-14 02:17:30

标签: 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'}]

2 个答案:

答案 0 :(得分:3)

可以这样做:

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])}

答案 1 :(得分:2)

另外两种方式:

<强>#1

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

order_hashes1(a1,a2)
  #=> [{:id=>3, :name=>"Banana"},
  #    {:id=>1, :name=>"Apple"},
  #    {:id=>2, :name=>"Orange"}]

<强>#2

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)

后记

order_hashes2从未走出大门,我并不感到惊讶,但我惊讶于构建哈希值然后用values_at提取值比@ sawa的解决方案快得多。我希望后者大部分时间都在执行index操作。

读者挑战者:还有很多其他方法可以解决这个问题。让我们看看您的建议,然后我们将它们添加到基准测试中。

相关问题