I'm looking for an elegant way of getting an array containing the maximum values between two arrays.
我正在寻找一种优雅的方法来获取包含两个数组之间的最大值的数组。
Meaning if there are two arrays:
意思是有两个数组:
a = [1, 5, 9]
b = [3, 2, 11]
The result should be:
结果应该是:
=> [3, 5, 11]
Assume both arrays are of the same size.
假设两个阵列的大小相同。
The code I use doesn't feel like a Ruby way to do that task:
我使用的代码不像Ruby那样做任务:
c = Array.new(a.size)
for i in 0...a.size
c[i] = [a[i], b[i]].max
end
3 个解决方案
#1
14
This should work:
这应该工作:
[a, b].transpose.map(&:max)
#=> [3, 5, 11]
transpose
returns [[1, 3], [5, 2], [9, 11]]
and map(&:max)
finds each sub array's maximum.
转置返回[[1,3],[5,2],[9,11]]和map(&:max)查找每个子数组的最大值。
a.zip(b)
(as suggested by Abe Voelker) is equivalent to [a, b].transpose
if both arrays have the same number of elements. If element size differs, transpose
would raise an exception:
a.zip(b)(如Abe Voelker所建议的)相当于[a,b] .transpose如果两个数组具有相同数量的元素。如果元素大小不同,转置将引发异常:
[1].zip([2,3])
#=> [[1,2]]
[[1], [2,3]].transpose
#=> IndexError: element size differs
Benchmarks
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
Output
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)
#2
7
a.zip(b).map(&:max) # => [3, 5, 11]
#3
4
How is the below ?
下面怎么样?
Note: Size should be equal of both the array.
注意:大小应该等于数组。
a = [1, 5, 9]
b = [3, 2, 11]
p a.size.times.map{|i| [a[i],b[i]].max}
# >> [3, 5, 11]
Or
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]
Or,
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]
Benchmark
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
output
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)
#1
14
This should work:
这应该工作:
[a, b].transpose.map(&:max)
#=> [3, 5, 11]
transpose
returns [[1, 3], [5, 2], [9, 11]]
and map(&:max)
finds each sub array's maximum.
转置返回[[1,3],[5,2],[9,11]]和map(&:max)查找每个子数组的最大值。
a.zip(b)
(as suggested by Abe Voelker) is equivalent to [a, b].transpose
if both arrays have the same number of elements. If element size differs, transpose
would raise an exception:
a.zip(b)(如Abe Voelker所建议的)相当于[a,b] .transpose如果两个数组具有相同数量的元素。如果元素大小不同,转置将引发异常:
[1].zip([2,3])
#=> [[1,2]]
[[1], [2,3]].transpose
#=> IndexError: element size differs
Benchmarks
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
Output
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)
#2
7
a.zip(b).map(&:max) # => [3, 5, 11]
#3
4
How is the below ?
下面怎么样?
Note: Size should be equal of both the array.
注意:大小应该等于数组。
a = [1, 5, 9]
b = [3, 2, 11]
p a.size.times.map{|i| [a[i],b[i]].max}
# >> [3, 5, 11]
Or
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]
Or,
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]
Benchmark
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
output
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)