Два других способа:
# 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"}]
Benchmark
Методы сравниваемых
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
был намного быстрее, чем решение @ Саввы. Я ожидаю, что последний провел большую часть своего времени, выполняя операцию index
.
Читатель-претендент: есть много других способов решения этой проблемы. Давайте посмотрим ваши предложения, и я добавлю их в бенчмарк.
@sawa: редактирование только для изменения стиля? Мне нравится это редко ... –
@BorisStitnicky Вы редактировали только, чтобы изменить стиль. Я вернул некоторые ненужные изменения, которые вы сделали. Пожалуйста, не изменяйте стиль OP, особенно от стиля колодца до стиля не образованного человека. Образованный человек не будет помещать пробелы в круглые скобки, скобки или скобки (это прекрасно, чтобы иметь окончания строки). – sawa
@BorisStitnicky Продолжение: (отлично иметь концы строк или отступы). Извините, если это звучит оскорбительно. Я специально не нацеливаюсь на вас. Я знаю, что многие программисты это делают, и меня это раздражает. – sawa