Concatenating variable number of Arrays?

Hi!

I have been searching for a method to concatenate several arrays.
A had an Array like this

 arr1 = [ [1,2,3], [4,5,6], [7,[8,9]] ]

and wanted to produce

 arr2 = [1, 2, 3, 4, 5, 6, 7, [8, 9]]

Looking at the methods of the Array class I found some methods that
do similar things, but none that fits exactly:

+          concatenate TWO Arrays

concat     concatenate TWO arrays destructively modifying
           the first

flatten    RECURSIVELY flattens elements into a new Array

The best way I have found until now, of doing what I want is

arr2 = arr1.inject([]) {|acc,x| acc.concat x}

But I feel that the thing I want to do (concatenating a variable
number arrays) is such a natural thing, that it deserves a cleaner
way of being expressed.

Have I missed some other method that does this in a readable way ?

/Johan Holmberg

Someone will probably come up with something better, but you could do it
with

arr1 = [ [1,2,3], [4,5,6], [7,[8,9]] ]
arr2 =
arr1.each { |array| arr2 += array }

HTH.

Andre

···

On Wed, 2004-01-14 at 13:33, Johan Holmberg wrote:

A had an Array like this

 arr1 = [ [1,2,3], [4,5,6], [7,[8,9]] ]

and wanted to produce

 arr2 = [1, 2, 3, 4, 5, 6, 7, [8, 9]]

“Johan Holmberg” holmberg@iar.se schrieb im Newsbeitrag
news:Pine.GSO.4.50.0401141612480.29527-100000@pjakkur.iar.se…

Hi!

I have been searching for a method to concatenate several arrays.
A had an Array like this

 arr1 = [ [1,2,3], [4,5,6], [7,[8,9]] ]

and wanted to produce

 arr2 = [1, 2, 3, 4, 5, 6, 7, [8, 9]]

Looking at the methods of the Array class I found some methods that
do similar things, but none that fits exactly:

+          concatenate TWO Arrays

concat     concatenate TWO arrays destructively modifying
           the first

flatten    RECURSIVELY flattens elements into a new Array

The best way I have found until now, of doing what I want is

arr2 = arr1.inject([]) {|acc,x| acc.concat x}

That’s exactly what I’d do.

But I feel that the thing I want to do (concatenating a variable
number arrays) is such a natural thing, that it deserves a cleaner
way of being expressed.

All other ways that I can think of are more verbose and not necessarily
cleander - let alone faster. The version using each would look like

arr2=
arr1.each {|x| arr2.concat x}

Not really an improvement IMHO.

Have I missed some other method that does this in a readable way ?

I don’t think so.

robert

I have been searching for a method to concatenate several arrays.
A had an Array like this

 arr1 = [ [1,2,3], [4,5,6], [7,[8,9]] ]

and wanted to produce

 arr2 = [1, 2, 3, 4, 5, 6, 7, [8, 9]]

[snip]

But I feel that the thing I want to do (concatenating a variable
number arrays) is such a natural thing, that it deserves a cleaner
way of being expressed.

how about arr1.flatten_once ?

http://raa.ruby-lang.org/list.rhtml?name=flattenx

···

On Thu, 15 Jan 2004 00:33:41 +0900, Johan Holmberg wrote:


Simon Strandgaard

The best way I have found until now, of doing what I want is

arr2 = arr1.inject([]) {|acc,x| acc.concat x}

You can also use “+” here:

arr2 = arr1.inject() { |a,x| a + x }

But I feel that the thing I want to do (concatenating a variable
number arrays) is such a natural thing, that it deserves a cleaner
way of being expressed.

If you extend Symbol like this:

class Symbol
def to_proc
lambda { |a, b| a.send(self, b) }
end
end

You could also write

arr2 = arr1.inject(, &:+)

That’s pretty similar to how it is done in most functional programming
languages.

···

On Wed, 2004-01-14 at 16:33, Johan Holmberg wrote:


o=lambda{|o|p o};O=Struct.new(:a,:b,:c);e=%q((?h,(?h,(?\ ,(?s,(?u,(74)),
(?t)),(?t,(?o,(?n,(?a))))),(82,(?r,(?e),(32)),(32,(98,(?u),(?y)))
)),
(?r,(99,(97),(?k,nil,(?e))),_(10))));def _(*a)O.new(*a)end;class O;def
e(&o)b&&b.e(&o);o[a];c&&c.e(&o)end;end;def p(o)print(‘’<<o)end;eval(e).e(&o)

“Florian Frank” flori@ping.de schrieb im Newsbeitrag
news:1074168191.4130.26.camel@lambda.eavesdrop.ping.de

···

On Wed, 2004-01-14 at 16:33, Johan Holmberg wrote:

The best way I have found until now, of doing what I want is

arr2 = arr1.inject([]) {|acc,x| acc.concat x}

You can also use “+” here:

arr2 = arr1.inject() { |a,x| a + x }

But I feel that the thing I want to do (concatenating a variable
number arrays) is such a natural thing, that it deserves a cleaner
way of being expressed.

If you extend Symbol like this:

class Symbol
def to_proc
lambda { |a, b| a.send(self, b) }
end
end

You could also write

arr2 = arr1.inject(, &:+)

That’s pretty similar to how it is done in most functional programming
languages.

Amazing! Only that it’s less efficient since your approach creates more
temporary arrays.

Regards

robert

“Florian Frank” flori@ping.de schrieb im Newsbeitrag
[…]

If you extend Symbol like this:

class Symbol
def to_proc
lambda { |a, b| a.send(self, b) }
end
end

You could also write

arr2 = arr1.inject(, &:+)

That’s pretty similar to how it is done in most functional programming
languages.

Amazing! Only that it’s less efficient since your approach creates more
temporary arrays.

I agree.
Where can I read about ‘to_proc’ and how it works ?

To avoid “+” I tried to changing to “concat” and this seems to work too:

class Symbol
def to_proc
    lambda { |acc, x| acc.__send__(self, x) }
end
end

arr1 = [ [1,2,3], [4,5,6], [7,[8,9]] ]
arr2 = arr1.inject([], &:concat)

/Johan Holmberg

···

On Thu, 15 Jan 2004, Robert Klemme wrote:

Amazing! Only that it’s less efficient since your approach creates
more temporary arrays.

That’s true: But it seems very clean to me. :wink:

I agree.
Where can I read about ‘to_proc’ and how it works ?

This trick uses the function block_pass in eval.c. If you pass an object
with & operator to a method, a conversion to a Proc object is attempted
in this function, by calling to_proc on this object. Usually there are
only Method and Proc objects in Ruby that implement this method. But you
can also define your own classes with to_proc if you like. Actually it’s
an application of duck typing.

···

On 2004-01-16 00:03:39 +0900, Johan Holmberg wrote:


o=lambda{|o|p o};O=Struct.new(:a,:b,:c);e=%q((?h,(?h,(?\ ,(?s,(?u,(74)),
(?t)),(?t,(?o,(?n,(?a))))),(82,(?r,(?e),(32)),(32,(98,(?u),(?y)))
)),
(?r,(99,(97),(?k,nil,(?e))),_(10))));def _(*a)O.new(*a)end;class O;def
e(&o)b&&b.e(&o);o[a];c&&c.e(&o)end;end;def p(o)print(‘’<<o)end;eval(e).e(&o)

[…]

I agree.
Where can I read about ‘to_proc’ and how it works ?

This trick uses the function block_pass in eval.c. If you pass an object
with & operator to a method, a conversion to a Proc object is attempted
in this function, by calling to_proc on this object. Usually there are
only Method and Proc objects in Ruby that implement this method. But you
can also define your own classes with to_proc if you like. Actually it’s
an application of duck typing.

Thanks for the explanation.
Is this documented somewhere or have you found out by reading the
code ?

One thing I wonder is if the ‘Symbol.to_proc’ method you described
is too global. What if we would like to define the method in a
different way somewhere else ?

Or is it poosible to define ‘Symbol.to_proc’ in a natural way ?
And in that case, why isn’t it already built into Ruby ?

/Johan Holmberg

···

On Fri, 16 Jan 2004, Florian Frank wrote:

On 2004-01-16 00:03:39 +0900, Johan Holmberg wrote: