我正在寻找一种优雅的方式来获取包含两个数组之间最大值的数组。
意思是如果有两个数组:
a = [1, 5, 9]
b = [3, 2, 11]
结果应该是:
=> [3, 5, 11]
假设两个数组的大小相同。
我使用的代码感觉不像是完成该任务的 Ruby 方式:
c = Array.new(a.size)
for i in 0...a.size
c[i] = [a[i], b[i]].max
end
我正在寻找一种优雅的方式来获取包含两个数组之间最大值的数组。
意思是如果有两个数组:
a = [1, 5, 9]
b = [3, 2, 11]
结果应该是:
=> [3, 5, 11]
假设两个数组的大小相同。
我使用的代码感觉不像是完成该任务的 Ruby 方式:
c = Array.new(a.size)
for i in 0...a.size
c[i] = [a[i], b[i]].max
end
这应该有效:
[a, b].transpose.map(&:max)
#=> [3, 5, 11]
transpose
返回[[1, 3], [5, 2], [9, 11]]
并map(&:max)
找到每个子数组的最大值。
a.zip(b)
(如 Abe Voelker 所建议的那样)等效于[a, b].transpose
两个数组是否具有相同数量的元素。如果元素大小不同,transpose
将引发异常:
[1].zip([2,3])
#=> [[1,2]]
[[1], [2,3]].transpose
#=> IndexError: element size differs
require 'benchmark'
a = (1..1000).to_a
b = a.reverse
n = 1000
Benchmark.bm(10) do |x|
x.report("transpose") { n.times { [a,b].transpose.map(&:max) } }
x.report("zip") { n.times { a.zip(b).map(&:max) } }
x.report("lazy.zip") { n.times { a.lazy.zip(b).map(&:max).to_a } }
x.report("loop (max)") { n.times { a.size.times.map{|i| [a[i],b[i]].max} } }
x.report("loop (>?:)") { n.times { a.size.times.map{|i| a[i]>b[i] ? a[i] : b[i] } } }
end
输出
user system total real
transpose 0.430000 0.000000 0.430000 ( 0.428760)
zip 0.420000 0.000000 0.420000 ( 0.415070)
lazy.zip 1.010000 0.000000 1.010000 ( 1.009173)
loop (max) 0.490000 0.000000 0.490000 ( 0.489015)
loop (>?:) 0.150000 0.000000 0.150000 ( 0.151461)
a.zip(b).map(&:max) # => [3, 5, 11]
下面怎么样?
注意:大小应该等于两个数组。
a = [1, 5, 9]
b = [3, 2, 11]
p a.size.times.map{|i| [a[i],b[i]].max}
# >> [3, 5, 11]
或者
a = [1, 5, 9]
b = [3, 2,11]
p a.size.times.map{|i| a[i]>b[i] ? a[i] : b[i] }
# >> [3, 5, 11]
或者,
a = [1, 5, 9]
b = [3, 2, 11]
p a.each_index.map{|i| a[i]>b[i] ? a[i] : b[i] }
# >> [3, 5, 11]
基准
require 'benchmark'
iterations = 10_000
a = [1, 5, 9]
b = [3, 2,11]
def stefan(a,b)
[a, b].transpose.map(&:max)
end
def abe(a,b)
a.zip(b).map(&:max)
end
def babai1(a,b)
a.size.times.map{|i| a[i]>b[i] ? a[i] : b[i] }
end
def babai2(a,b)
a.size.times.map{|i| [a[i],b[i]].max}
end
def babai3(a,b)
a.each_index.map{|i| a[i]>b[i] ? a[i] : b[i] }
end
Benchmark.bm do |bm|
bm.report('Stefan') do
iterations.times do
stefan(a,b)
end
end
bm.report('Abe') do
iterations.times do
abe(a,b)
end
end
bm.report('babai1') do
iterations.times do
babai1(a,b)
end
end
bm.report('babai2') do
iterations.times do
babai2(a,b)
end
end
bm.report('babai3') do
iterations.times do
babai3(a,b)
end
end
end
输出
user system total real
Stefan 0.047000 0.000000 0.047000 ( 0.046874)
Abe 0.047000 0.000000 0.047000 ( 0.046873)
babai1 0.031000 0.000000 0.031000 ( 0.031249)
babai2 0.062000 0.000000 0.062000 ( 0.062497)
babai3 0.032000 0.000000 0.032000 ( 0.031249)