ruby map a function over multiple arrays

Viewed 173

I have 2 arrays

   asc = [0, 1, 2, 3, 4, 5]
   dsc = [5, 4, 3, 2, 1, 0]

I want a new array that is results of multiplying each corresponding item in asc and dsc

I'm used to Clojure where I would just map

(map #(* %1 %2) asc dsc) ;=> (0 4 6 6 4 0)

Is their an equivalent in Ruby, what would be the idiomatic way to do this in Ruby?

I'm new to Ruby but it seems to have really nice concise solutions, so I assume I'm missing something.

Do I just write:

i = 0
res = []

while i < asc.length() do
  res.append(asc[i] * dsc[i])
end
4 Answers

Use zip to combine each element with its corresponding in two element array and than map

asc.zip(dsc).map { |a, b| a * b }
 => [0, 4, 6, 6, 4, 0] 

Use map and with_index:

asc = [0, 1, 2, 3, 4, 5]
dsc = [5, 4, 3, 2, 1, 0]
res = asc.map.with_index{ |el, i| el * dsc[i] }
puts res.inspect
# [0, 4, 6, 6, 4, 0]

Alternatively, use each_index and map:

res = asc.each_index.map{ |i| asc[i] * dsc[i] }

It appears that dsc ("descending") is derived from asc ("ascending"), in which case you could write:

asc.each_index.map { |i| asc[i] * asc[-i-1] } 
  #=> [0, 4, 6, 6, 4, 0]

You could also write:

[asc, dsc].transpose.map { |a,d| a*d }
  #=> [0, 4, 6, 6, 4, 0]

or:

require 'matrix'

Matrix[asc].hadamard_product(Matrix[dsc]).to_a.first
  #=> [0, 4, 6, 6, 4, 0]

See Matrix#hadamard_product.

You could also write like below:

asc = [0, 1, 2, 3, 4, 5]
dsc = [5, 4, 3, 2, 1, 0]

p asc.zip(dsc).collect{|z| z.inject(:*)}
[0, 4, 6, 6, 4, 0]
Related