# Multiply all array with array

**URL:** <https://rubytalk.org/t/multiply-all-array-with-array/7691>\
**Category:** ruby-talk\
**Created:** [29 August 2003 11:18 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691 "2003-08-29T11:18:14Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![ibotty](https://avatars.discourse-cdn.com/v4/letter/i/4af34b/32.png) [@ibotty](https://rubytalk.org/u/ibotty)\
**Post date:** [29 August 2003 11:18 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/1 "2003-08-29T11:18:14Z")

</div>

before i spent to many words describing something so simple:

say, i have:  
a = [1,2,3] and b = [4,5,6]  
and i want to get another array, with c[ix] = a[ix] \* b[ix].  
(i want to get c = [4,10,18])

is there a builtin function in array.rb (that i have missed).

atm, i use a block to traverse thru every single element, but this still  
makes one big or 2 small lines.  
(e. g.: c =[]; a.each\_with\_index{ |ix| c[ix] = a[ix] \* b[ix] } )

this should be way more elegant 😉

~ibotty

---

<div class="post-metadata">

**Author:** ![Martin\_DeMello1](https://avatars.discourse-cdn.com/v4/letter/m/3be4f8/32.png) [@Martin\_DeMello1](https://rubytalk.org/u/Martin_DeMello1)\
**Post date:** [29 August 2003 11:38 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/2 "2003-08-29T11:38:13Z")

</div>

Not quite, but for parallel traversing made easier

a.zip(b).map {|i, j| i\*j}

martin

> **···**
>
> ibotty [me@ibotty.net](mailto:me@ibotty.net) wrote:
> 
> > before i spent to many words describing something so simple:
> > 
> > say, i have:  
> > a = [1,2,3] and b = [4,5,6]  
> > and i want to get another array, with c[ix] = a[ix] \* b[ix].  
> > (i want to get c = [4,10,18])
> > 
> > is there a builtin function in array.rb (that i have missed).

---

<div class="post-metadata">

**Author:** ![Carlos](https://avatars.discourse-cdn.com/v4/letter/c/ecae2f/32.png) [@Carlos](https://rubytalk.org/u/Carlos)\
**Post date:** [29 August 2003 12:11 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/3 "2003-08-29T12:11:39Z")

</div>

> say, i have:  
> a = [1,2,3] and b = [4,5,6]  
> and i want to get another array, with c[ix] = a[ix] \* b[ix].  
> (i want to get c = [4,10,18])

a.zip(b).map { |x,y| x\*y } # =\> [4, 10, 18]

---

<div class="post-metadata">

**Author:** ![Wesley\_J\_Landaker](https://avatars.discourse-cdn.com/v4/letter/w/a698b9/32.png) [@Wesley\_J\_Landaker](https://rubytalk.org/u/Wesley_J_Landaker)\
**Post date:** [29 August 2003 13:55 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/4 "2003-08-29T13:55:25Z")

</div>

Apparently, ibotty recently wrote:

> before i spent to many words describing something so simple:
> 
> say, i have:  
> a = [1,2,3] and b = [4,5,6]  
> and i want to get another array, with c[ix] = a[ix] \* b[ix].  
> (i want to get c = [4,10,18])
> 
> is there a builtin function in array.rb (that i have missed).
> 
> atm, i use a block to traverse thru every single element, but this still  
> makes one big or 2 small lines.  
> (e. g.: c =; a.each\_with\_index{ |ix| c[ix] = a[ix] \* b[ix] } )
> 
> this should be way more elegant 😉

I don’t know if this is more elegant to you or not, but here is another way:

c = a.zip(b).map {|x| x[0] \* x[1]}

Wes

---

<div class="post-metadata">

**Author:** ![Denis\_Mertz](https://avatars.discourse-cdn.com/v4/letter/d/c57346/32.png) [@Denis\_Mertz](https://rubytalk.org/u/Denis_Mertz)\
**Post date:** [29 August 2003 14:58 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/5 "2003-08-29T14:58:38Z")

</div>

ibotty [me@ibotty.net](mailto:me@ibotty.net) wrote in message news:[1062154916.838157@elch.in-berlin.de](mailto:1062154916.838157@elch.in-berlin.de)…

> before i spent to many words describing something so simple:
> 
> say, i have:  
> a = [1,2,3] and b = [4,5,6]  
> and i want to get another array, with c[ix] = a[ix] \* b[ix].  
> (i want to get c = [4,10,18])
> 
> is there a builtin function in array.rb (that i have missed).
> 
> atm, i use a block to traverse thru every single element, but this still  
> makes one big or 2 small lines.  
> (e. g.: c =; a.each\_with\_index{ |ix| c[ix] = a[ix] \* b[ix] } )
> 
> this should be way more elegant 😉

you can use the Enumerable#zip and Enumerable#collect methods:

c = a.zip(b).collect{|a\_elt, b\_elt| a\_elt\*b\_elt}

i dont see more elegant 🙂

Ciao  
Denis

---

<div class="post-metadata">

**Author:** ![Wesley\_J\_Landaker](https://avatars.discourse-cdn.com/v4/letter/w/a698b9/32.png) [@Wesley\_J\_Landaker](https://rubytalk.org/u/Wesley_J_Landaker)\
**Post date:** [29 August 2003 13:57 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/6 "2003-08-29T13:57:36Z")

</div>

Apparently, Martin DeMello recently wrote:

> **···**
>
> > ibotty [me@ibotty.net](mailto:me@ibotty.net) wrote:
> > 
> > > before i spent to many words describing something so simple:
> > > 
> > > say, i have:  
> > > a = [1,2,3] and b = [4,5,6]  
> > > and i want to get another array, with c[ix] = a[ix] \* b[ix].  
> > > (i want to get c = [4,10,18])
> > > 
> > > is there a builtin function in array.rb (that i have missed).
> > 
> > Not quite, but for parallel traversing made easier
> > 
> > a.zip(b).map {|i, j| i\*j}
> 
> Hey, this is just like what I just posted, except better! =)
> 
> (That’s what I get for replying before reading the rest of the thread… 😉
> 
> Wes

---

<div class="post-metadata">

**Author:** ![ibotty](https://avatars.discourse-cdn.com/v4/letter/i/4af34b/32.png) [@ibotty](https://rubytalk.org/u/ibotty)\
**Post date:** [29 August 2003 15:18 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/7 "2003-08-29T15:18:41Z")

</div>

thx all ya guys,

> > is there a builtin function in array.rb (that i have missed).
> 
> Not quite, but for parallel traversing made easier
> 
> a.zip(b).map {|i, j| i\*j}

this is indeed much more elegant.

but because array \* array is not defined, me thinks. one could implement  
(this simple case) this way.

just my 2¢, though

~ibotty

---

<div class="post-metadata">

**Author:** ![Charles\_D\_Hixson](https://avatars.discourse-cdn.com/v4/letter/c/e495f1/32.png) [@Charles\_D\_Hixson](https://rubytalk.org/u/Charles_D_Hixson)\
**Post date:** [30 August 2003 18:06 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/8 "2003-08-30T18:06:47Z")

</div>

Martin DeMello wrote:

> > before i spent to many words describing something so simple:
> > 
> > say, i have:  
> > a = [1,2,3] and b = [4,5,6]  
> > and i want to get another array, with c[ix] = a[ix] \* b[ix].  
> > (i want to get c = [4,10,18])
> > 
> > is there a builtin function in array.rb (that i have missed).
> 
> Not quite, but for parallel traversing made easier
> 
> a.zip(b).map {|i, j| i\*j}
> 
> martin

But isn’t that the wrong answer?  
I thought that [1, 2, 3] \* [4, 5, 6] would be:  
[[4, 5, 6],  
[8, 10, 12],  
[12, 15, 18]  
] or some such (I might have reversed the arguments–and I don’t think  
it’s commutative. [Admittedly, it’s been a few decades since I did such  
math.]). And if you meant the dot product rather than the cross  
product, you would get a scalar.

> **···**
>
> > ibotty [me@ibotty.net](mailto:me@ibotty.net) wrote:

---

<div class="post-metadata">

**Author:** ![Olivier\_Nenert](https://avatars.discourse-cdn.com/v4/letter/o/958977/32.png) [@Olivier\_Nenert](https://rubytalk.org/u/Olivier_Nenert)\
**Post date:** [29 August 2003 15:26 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/9 "2003-08-29T15:26:17Z")

</div>

> thx all ya guys,
> 
> > > is there a builtin function in array.rb (that i have missed).
> > 
> > Not quite, but for parallel traversing made easier
> > 
> > a.zip(b).map {|i, j| i\*j}
> 
> this is indeed much more elegant.
> 
> but because array \* array is not defined, me thinks. one could implement  
> (this simple case) this way.  
> but I think most people (or at least I) would expect a cartesian product  
> as the result of this operator… it would be much more useful because it  
> would work with any two arrays,  
> not just two arrays with the same size. (oh well it could also work like  
> you say with arrays of different sizes if we fill with zeros the shorter  
> one :))

cheers…

Olivier.

---

<div class="post-metadata">

**Author:** ![Martin\_DeMello1](https://avatars.discourse-cdn.com/v4/letter/m/3be4f8/32.png) [@Martin\_DeMello1](https://rubytalk.org/u/Martin_DeMello1)\
**Post date:** [29 August 2003 15:38 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/10 "2003-08-29T15:38:44Z")

</div>

Here’s a handy generalisation of the method:

class Array  
def mapwith(\*args, &block)  
if block\_given?  
zip(\*args).collect {|i, j| yield i, j}  
else  
f = args.pop  
zip(\*args).collect {|i, j| i.send(f, j)}  
end  
end  
end

p [1,2,3].mapwith([4,5,6]) {|i,j| i_j}  
p [1,2,3].mapwith([4,5,6], :_)

martin

> **···**
>
> ibotty [me@ibotty.net](mailto:me@ibotty.net) wrote:
> 
> > thx all ya guys,
> > 
> > > > is there a builtin function in array.rb (that i have missed).
> > > 
> > > Not quite, but for parallel traversing made easier
> > > 
> > > a.zip(b).map {|i, j| i\*j}
> > 
> > this is indeed much more elegant.
> > 
> > but because array \* array is not defined, me thinks. one could implement  
> > (this simple case) this way.

---

<div class="post-metadata">

**Author:** ![HAL\_9000](https://avatars.discourse-cdn.com/v4/letter/h/90ced4/32.png) [@HAL\_9000](https://rubytalk.org/u/HAL_9000)\
**Post date:** [30 August 2003 18:09 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/11 "2003-08-30T18:09:43Z")

</div>

Charles Hixson wrote:

> Martin DeMello wrote:
> 
> > > before i spent to many words describing something so simple:
> > > 
> > > say, i have:  
> > > a = [1,2,3] and b = [4,5,6]  
> > > and i want to get another array, with c[ix] = a[ix] \* b[ix].  
> > > (i want to get c = [4,10,18])
> > > 
> > > is there a builtin function in array.rb (that i have missed).
> > 
> > Not quite, but for parallel traversing made easier
> > 
> > a.zip(b).map {|i, j| i\*j}
> > 
> > martin
> 
> But isn’t that the wrong answer?  
> I thought that [1, 2, 3] \* [4, 5, 6] would be:  
> [[4, 5, 6],  
> [8, 10, 12],  
> [12, 15, 18]  
> ] or some such (I might have reversed the arguments–and I don’t think  
> it’s commutative. [Admittedly, it’s been a few decades since I did such  
> math.]). And if you meant the dot product rather than the cross  
> product, you would get a scalar.

I think this is what the original poster wanted. He doesn’t  
seem to be asking for a cross product OR a dot product as  
far as I can tell, but just a nice idiomatic way of doing  
a specific operation.

Hal

> **···**
>
> > > ibotty [me@ibotty.net](mailto:me@ibotty.net) wrote:

---

<div class="post-metadata">

**Author:** ![Sabbyxtabby](https://avatars.discourse-cdn.com/v4/letter/s/f08c70/32.png) [@Sabbyxtabby](https://rubytalk.org/u/Sabbyxtabby)\
**Post date:** [30 August 2003 00:00 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/12 "2003-08-30T00:00:11Z")

</div>

> > > Not quite, but for parallel traversing made easier
> > > 
> > > a.zip(b).map {|i, j| i\*j}
> > 
> > this is indeed much more elegant.
> > 
> > but because array \* array is not defined, me thinks. one could implement  
> > (this simple case) this way.

In APL, \* and other operators work like this, element-by-element.

> Here’s a handy generalisation of the method:
> 
> class Array  
> def mapwith(\*args, &block)  
> if block\_given?  
> zip(\*args).collect {|i, j| yield i, j}  
> else  
> f = args.pop  
> zip(\*args).collect {|i, j| i.send(f, j)}  
> end  
> end  
> end
> 
> p [1,2,3].mapwith([4,5,6]) {|i,j| i_j}  
> p [1,2,3].mapwith([4,5,6], :_)

Should #mapwith work with 3 or more arrays like #zip does?

p [1,2,3].mapwith([4,5,6], [7,8,9]) {|i,j,k| i\*j+k}

Allowing #zip to take a block has been discussed before. Here’s yet  
another implementation:

class Array  
alias \_zip zip  
def zip(\*args)  
if block\_given?  
\_zip(\*args).map {|a| yield a}  
else  
\_zip(\*args)  
end  
end  
end

p [1,2,3].zip([4,5,6], [7,8,9]) {|i,j,k| i\*j+k}

Unfortunately, it doesn’t allow taking a symbol to an operator (:\*)  
like #mapwith does.

> **···**
>
> Martin DeMello [martindemello@yahoo.com](mailto:martindemello@yahoo.com) wrote:
> 
> > ibotty [me@ibotty.net](mailto:me@ibotty.net) wrote:

---

<div class="post-metadata">

**Author:** ![ibotty](https://avatars.discourse-cdn.com/v4/letter/i/4af34b/32.png) [@ibotty](https://rubytalk.org/u/ibotty)\
**Post date:** [30 August 2003 22:03 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/13 "2003-08-30T22:03:50Z")

</div>

> > > > a = [1,2,3] and b = [4,5,6]  
> > > > and i want to get another array, with c[ix] = a[ix] \* b[ix].  
> > > > (i want to get c = [4,10,18])

> > > a.zip(b).map {|i, j| i\*j}  
> > > But isn’t that the wrong answer?  
> > > […]  
> > > And if you meant the dot product rather than the cross  
> > > product, you would get a scalar.

> I think this is what the original poster wanted. He doesn’t  
> seem to be asking for a cross product OR a dot product as  
> far as I can tell, but just a nice idiomatic way of doing  
> a specific operation.

we do have a Vector (defined in matrix.rb (in 1.6 at least))  
this Vector should define cross and dot product (well, cross product it  
should not necessarily define, too much specific to three dimension  
vectors, huh? 😉  
so in short, i think this a product of two arrays should not be a cross or  
dot product. never. use a vector instead, if you want to.

btw: this is not meant to be rude, but why put something in array, when it  
belongs to something else.

~ibotty

---

<div class="post-metadata">

**Author:** ![Martin\_DeMello1](https://avatars.discourse-cdn.com/v4/letter/m/3be4f8/32.png) [@Martin\_DeMello1](https://rubytalk.org/u/Martin_DeMello1)\
**Post date:** [30 August 2003 20:23 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/14 "2003-08-30T20:23:31Z")

</div>

> Should #mapwith work with 3 or more arrays like #zip does?
> 
> p [1,2,3].mapwith([4,5,6], [7,8,9]) {|i,j,k| i\*j+k}

Right you are. I’ll rework it in the a.m. - too sleepy right now 🙂

> Allowing #zip to take a block has been discussed before. Here’s yet  
> another implementation:
> 
> class Array  
> alias \_zip zip  
> def zip(\*args)  
> if block\_given?  
> \_zip(\*args).map {|a| yield a}  
> else  
> \_zip(\*args)  
> end  
> end  
> end
> 
> p [1,2,3].zip([4,5,6], [7,8,9]) {|i,j,k| i\*j+k}
> 
> Unfortunately, it doesn’t allow taking a symbol to an operator (:\*)  
> like #mapwith does.

The symbol was my main motivation for writing it, actually - map {|x,y|  
x\*y} just felt redundant.

martin

> **···**
>
> Sabby and Tabby [sabbyxtabby@yahoo.com](mailto:sabbyxtabby@yahoo.com) wrote:

---

<div class="post-metadata">

**Author:** ![Harry\_Ohlsen1](https://avatars.discourse-cdn.com/v4/letter/h/a88e57/32.png) [@Harry\_Ohlsen1](https://rubytalk.org/u/Harry_Ohlsen1)\
**Post date:** [1 September 2003 23:01 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/15 "2003-09-01T23:01:50Z")

</div>

ibotty wrote:

> … (well, cross product it  
> should not necessarily define, too much specific to three dimension  
> vectors, huh? 😉

Perhaps we need a Tensor class :-).

If there was such one, maybe I’d finally have a hope of understanding those darned things!

Harry O.

---

<div class="post-metadata">

**Author:** ![Martin\_DeMello1](https://avatars.discourse-cdn.com/v4/letter/m/3be4f8/32.png) [@Martin\_DeMello1](https://rubytalk.org/u/Martin_DeMello1)\
**Post date:** [31 August 2003 12:25 UTC](https://rubytalk.org/t/multiply-all-array-with-array/7691/16 "2003-08-31T12:25:27Z")

</div>

class Array  
def mapwith(\*args, &block)  
if block\_given?  
zip(\*args).collect {|i| yield \*i}  
else  
f = args.pop  
zip(\*args).collect {|i, \*j| i.send(f, \*j)}  
end  
end  
end

p [1,2,3].mapwith([4,5,6], [7,8,9]) {|i,j,k| i\*j+k}  
p [[1],[2],[3]].mapwith([4,5,6], [7,8,9], :push)

martin

> **···**
>
> Martin DeMello [martindemello@yahoo.com](mailto:martindemello@yahoo.com) wrote:
> 
> > Sabby and Tabby [sabbyxtabby@yahoo.com](mailto:sabbyxtabby@yahoo.com) wrote:
> > 
> > > Should #mapwith work with 3 or more arrays like #zip does?
> > > 
> > > p [1,2,3].mapwith([4,5,6], [7,8,9]) {|i,j,k| i\*j+k}
