Reputation: 1423
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:
c = Array.new(a.size)
for i in 0...a.size
c[i] = [a[i], b[i]].max
end
Upvotes: 7
Views: 2523
Reputation: 118289
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)
Upvotes: 4
Reputation: 114237
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.
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:
[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
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)
Upvotes: 14