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
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With