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