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)