# Array1 + array2 newb question

**URL:** <https://rubytalk.org/t/array1-array2-newb-question/21531>\
**Category:** ruby-talk\
**Created:** [13 October 2005 08:51 UTC](https://rubytalk.org/t/array1-array2-newb-question/21531 "2005-10-13T08:51:19Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kroeger\_Simon\_ext](https://avatars.discourse-cdn.com/v4/letter/k/5daacb/32.png) [@Kroeger\_Simon\_ext](https://rubytalk.org/u/Kroeger_Simon_ext)\
**Post date:** [13 October 2005 08:51 UTC](https://rubytalk.org/t/array1-array2-newb-question/21531/1 "2005-10-13T08:51:19Z")

</div>

> From: Robert Klemme [mailto:bob.news@gmx.net]  
> Since there hasn't been an #inject solution so far... 🙂

hmm, is the gateway broken again?

a1.inject(){|s, x| s + a2.map {|y| [x, y]}}

(posted 1 hour ago)

cheers

Simon

---

<div class="post-metadata">

**Author:** ![Robert](https://avatars.discourse-cdn.com/v4/letter/r/e95f7d/32.png) [@Robert](https://rubytalk.org/u/Robert)\
**Post date:** [13 October 2005 09:46 UTC](https://rubytalk.org/t/array1-array2-newb-question/21531/2 "2005-10-13T09:46:54Z")

</div>

Kroeger, Simon (ext) wrote:

> > From: Robert Klemme [mailto:bob.news@gmx.net]  
> > Since there hasn't been an #inject solution so far... 🙂
> 
> hmm, is the gateway broken again?
> 
> a1.inject(){|s, x| s + a2.map {|y| [x, y]}}
> 
> (posted 1 hour ago)

No, it's here. Can't tell though whether I just overlooked it or whether  
the posting arrived here after I wrote mine.

And note that your version has the disadvantage that you copy s all the  
time. Using concat is more efficient. Even if you use that there's an  
intermediate array per x value that is dropped again. That's why my  
solution just appends two element arrays to the collecting array. 🙂

Kind regards

&nbsp;&nbsp;&nbsp;&nbsp;robert

---

<div class="post-metadata">

**Author:** ![daz](https://avatars.discourse-cdn.com/v4/letter/d/87869e/32.png) [@daz](https://rubytalk.org/u/daz)\
**Post date:** [13 October 2005 12:56 UTC](https://rubytalk.org/t/array1-array2-newb-question/21531/3 "2005-10-13T12:56:56Z")

</div>

Robert Klemme wrote:

> Kroeger, Simon (ext) wrote:  
> \>\> From: Robert Klemme [mailto:bob.news@gmx.net]  
> \>\> Since there hasn't been an #inject solution so far... 🙂  
> \>  
> \> hmm, is the gateway broken again?  
> \>  
> \> a1.inject(){|s, x| s + a2.map {|y| [x, y]}}  
> \>  
> \> (posted 1 hour ago)
> 
> No, it's here. Can't tell though whether I just overlooked it  
> or whether the posting arrived here after I wrote mine.
> 
> And note that your version has the disadvantage [...]

A more significant disadvantage is that you both posted solutions  
with equivalent results but for a slightly different problem than  
the one posed by the OP 😉

> [...] that you copy s all the time.

As did my solution.

> Using concat is more efficient.

That's usually safe to say ... but check the b/marks.

> That's why my solution just appends two element arrays to  
> the collecting array. 🙂

.... And ends up 3rd out of 3 in the b/mk race 😃

> Kind regards
> 
> &nbsp;&nbsp;&nbsp;&nbsp;robert

After making the necessary corrections:

> **···**
>
> #--------------------  
> require 'benchmark'  
> include Benchmark
> 
> a1 = [1,2,3]  
> a2 = %w{a b c}
> 
> BMN = 50000 # \<------ ?whatever?  
> bm(7) do |bx|  
> &nbsp;&nbsp;bx.report('d-') { BMN.times { dz = ; a2.each{|s| dz += a1.map {|y| [y, s]}} }}  
> &nbsp;&nbsp;bx.report('s-') { BMN.times { sk = a2.inject(){|s,x| s + a1.map {|y| [y, x]}} }}  
> &nbsp;&nbsp;bx.report('r-') { BMN.times { rk = a2.inject(){|r,x| a1.each {|y| r \<\< [y,x]}; r} }}  
> &nbsp;&nbsp;&nbsp;&nbsp;GC.start ; GC.disable  
> &nbsp;&nbsp;bx.report('dz') { BMN.times { dz = ; a2.each{|s| dz += a1.map {|y| [y, s]}} }}  
> &nbsp;&nbsp;&nbsp;&nbsp;GC.start ; GC.disable  
> &nbsp;&nbsp;bx.report('sk') { BMN.times { sk = a2.inject(){|s,x| s + a1.map {|y| [y, x]}} }}  
> &nbsp;&nbsp;&nbsp;&nbsp;GC.start ; GC.disable  
> &nbsp;&nbsp;bx.report('rk') { BMN.times { rk = a2.inject(){|r,x| a1.each {|y| r \<\< [y,x]}; r} }}  
> end
> 
> =begin  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user system total real  
> d- 5.857000 0.000000 5.857000 ( 5.880000)  
> s- 7.145000 0.000000 7.145000 ( 7.140000)  
> r- 8.040000 0.000000 8.040000 ( 8.070000)  
> dz 5.415000 0.000000 5.415000 ( 5.440000)  
> sk 6.428000 0.000000 6.428000 ( 6.420000)  
> rk 7.353000 0.000000 7.353000 ( 7.360000)  
> =end  
> #--------------------
> 
> IMHO - #inject is very useful but I don't see the advantage  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of using it to hide an initial x = and  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;subjecting it to being flung round in circles.
> 
> As you can see, it doesn't gain anything, here.
> 
> (Not a squabble 🙂
> 
> daz

---

<div class="post-metadata">

**Author:** ![Robert](https://avatars.discourse-cdn.com/v4/letter/r/e95f7d/32.png) [@Robert](https://rubytalk.org/u/Robert)\
**Post date:** [13 October 2005 15:21 UTC](https://rubytalk.org/t/array1-array2-newb-question/21531/4 "2005-10-13T15:21:54Z")

</div>

daz wrote:

> Robert Klemme wrote:  
> A more significant disadvantage is that you both posted solutions  
> with equivalent results but for a slightly different problem than  
> the one posed by the OP 😉

Right. Shouldn't make a difference performance wise though.

> > That's why my solution just appends two element arrays to  
> > the collecting array. 🙂
> 
> ... And ends up 3rd out of 3 in the b/mk race 😃

It depends... (see below)

> IMHO - #inject is very useful but I don't see the advantage  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of using it to hide an initial x = and  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;subjecting it to being flung round in circles.
> 
> As you can see, it doesn't gain anything, here.
> 
> (Not a squabble 🙂

Your benchmark version crashed on my system because it used too much mem.  
IMHO GC times should be \*included\* because in a real world situation the  
time overhead incurred by massive object allocations and deallocations  
does in fact influence performance. However, with a modified script I get

17:05:03 [source]: ruby /c/temp/ruby/mappings.rb  
Rehearsal ------------------------------------------  
dz 5.719000 0.000000 5.719000 ( 5.733000)  
dzco 4.984000 0.000000 4.984000 ( 4.988000)  
sk 6.891000 0.000000 6.891000 ( 6.959000)  
co 6.187000 0.000000 6.187000 ( 6.193000)  
rk 5.625000 0.000000 5.625000 ( 5.674000)  
rk2 8.938000 0.000000 8.938000 ( 9.017000)  
rk3 9.000000 0.000000 9.000000 ( 9.074000)  
-------------------------------- total: 47.344000sec

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user system total real  
dz 5.719000 0.000000 5.719000 ( 5.762000)  
dzco 4.921000 0.000000 4.921000 ( 4.997000)  
sk 6.875000 0.000000 6.875000 ( 6.918000)  
co 6.234000 0.000000 6.234000 ( 6.270000)  
rk 5.641000 0.000000 5.641000 ( 5.669000)  
rk2 9.078000 0.000000 9.078000 ( 9.137000)  
rk3 9.078000 0.000000 9.078000 ( 9.118000)

Interestingly the double inject performs so bad. However the one inject  
version is approx as fast as "dz". But the clear winner is \*surprise  
surprise\*

dz = ; a2.each{|s| dz.concat a1.map {|y| [y, s]}}

Would be interesting to see how timings differ for larger arrays...

17:15:43 [source]: ruby /c/temp/ruby/mappings-2.rb  
96  
Rehearsal ------------------------------------------  
dz 3.375000 0.015000 3.390000 ( 3.405000)  
dzco 3.485000 0.000000 3.485000 ( 3.532000)  
sk 3.453000 0.000000 3.453000 ( 3.478000)  
co 3.532000 0.000000 3.532000 ( 3.581000)  
rk 3.984000 0.000000 3.984000 ( 4.030000)  
rk2 6.594000 0.000000 6.594000 ( 6.619000)  
rk3 6.640000 0.000000 6.640000 ( 6.663000)  
-------------------------------- total: 31.078000sec

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user system total real  
dz 3.344000 0.016000 3.360000 ( 3.370000)  
dzco 3.157000 0.000000 3.157000 ( 3.192000)  
sk 3.422000 0.000000 3.422000 ( 3.429000)  
co 3.203000 0.000000 3.203000 ( 3.240000)  
rk 3.266000 0.000000 3.266000 ( 3.256000)  
rk2 6.562000 0.000000 6.562000 ( 6.576000)  
rk3 7.031000 0.000000 7.031000 ( 7.117000)

Differences are much larger. Still I have no clue why the double inject  
version is so slow...

Kind regards

&nbsp;&nbsp;&nbsp;&nbsp;robert

[mappings.rb](https://rubytalk.org/uploads/short-url/b0Az6w00ezmaApJWnxDe6VoHJGv.rb) (768 Bytes)

[mappings-2.rb](https://rubytalk.org/uploads/short-url/819q4D3ueXjdY8JUUKQ9mxJfyfn.rb) (818 Bytes)

---

<div class="post-metadata">

**Author:** ![daz](https://avatars.discourse-cdn.com/v4/letter/d/87869e/32.png) [@daz](https://rubytalk.org/u/daz)\
**Post date:** [13 October 2005 22:31 UTC](https://rubytalk.org/t/array1-array2-newb-question/21531/5 "2005-10-13T22:31:59Z")

</div>

Robert Klemme wrote:

> daz wrote:  
> \> Robert Klemme wrote:
> 
> dz = ; a2.each{|s| dz.concat a1.map {|y| [y, s]}}

That's enlightening about #concat. When you mentioned  
it in reply to Simon, I read it as a reference to your  
use of \<\<. #concat is one of those methods that wasn't  
in my vocabulary -- I thought it was an alias for + or  
something ... not so.

Most of the time I use \<\< unless it causes unrequired  
nesting of arrays, then I go for +. What I hoped I was  
doing with + is what #concat does, i.e. splices to the  
receiving array without creating a new one.

As Douglas Adams almost wrote:  
&nbsp;&nbsp;"Well, that just about wraps it up for Array#+" 😉

Cheers,

daz

+ ....... Concatenation (produces a third array)  
concat .. Appends elements (think of as +! bang-method)  
push .... \<\<  
\<\< ...... Append object (alias of push)
