Metaprogramming - Array initialization

Hi,

In Ruby, we can declare array as explain in the doc:
http://ruby-doc.org/core/classes/Array.html#M002150

That makes possible many kind of use, such as:

Array.new(1, Array.new(3, Array.new(2, Array.new(1))))
=> [[[[nil], [nil]], [[nil], [nil]], [[nil], [nil]]]]

For my needs, I would like to use a code that declare an array of any
arrays that we want. I don’t know if it is possible.

If the previous example can be generated using a function like:
my_array = make_array(1, 3, 2, 1)

…this could be awesome!

Thank you for any comments and help.

Regards.

Paul A. wrote:

arrays that we want. I don’t know if it is possible.
The above is probably not what you want. Look:

a=Array.new(3, Array.new(2))
=> [[nil, nil], [nil, nil], [nil, nil]]

a[0][1] = 6
=> 6

a
=> [[nil, 6], [nil, 6], [nil, 6]]

Try using the block form:

a=Array.new(3) {Array.new(2)}
=> [[nil, nil], [nil, nil], [nil, nil]]

a[0][1] = 6
=> 6

a
=> [[nil, 6], [nil, nil], [nil, nil]]

Agree with Joel. Use the block form of the new method, or you’ll get
multiple references to the same object.
This piece of code I believe does the trick. (No fault handling
included,
and probably not the most elegant, perhaps since I’m quite new to Ruby.)

def make_array(*a)
a.flatten!
if a.size > 1
Array.new(a.shift){make_array(a)}
elsif a.size == 1
Array.new(a.shift)
end
end

irb(main):052:0> make_array(1, 3, 2, 1)
=> [[[[nil], [nil]], [[nil], [nil]], [[nil], [nil]]]]

Best regards,
Rolf

On Sat, Apr 24, 2010 at 11:48 PM, Joel VanderWerf

Very instructives and helpful answers. Many thanks!

A subtle improvement to the function, as I failed to remember that I
could
expand an array to multiple arguments again when calling the function
recursively:

def make_array(*a)
if a.size > 1
Array.new(a.shift){make_array(*a)}
elsif a.size == 1
Array.new(a.shift)
end
end

-Rolf

On 04/25/2010 12:35 AM, Rolf P. wrote:

Array.new(a.shift)

end
end

And what about the case of an empty argument list?

def make_array(*a)
case a.size
when 0
raise ArgumentError, “Need at least one dimension”
when 1
Array.new(a.shift)
else
Array.new(a.shift){make_array(*a)}
end
end

Kind regards

robert

Hi Joel,

You could construct the string that represents the command that would
generate the multidimensional array creation and lauch it with
instance_eval.

def make_array(input)

result = “”

for i in input
result = result + “Array.new(#{i},”
end

for i in input
result = result + “)”
end

instance_eval(result)

end

The code is not very bright (and also a lot of checks on the input
values
should be made before executing instance eval) but I hope you get an
idea.

Regards,
Vicente

Had a small issue w/1.9.1.

Here is mine (inspired by Vicente’s code):

def multi_array(*input)
instabce_eval input.map {|i| “Array.new(#{i}”}.join(“,”) + ‘)’ *
input.length
end

Definitely a cool way to make arrays.

Cheers,
Ed

Ed Howland

http://twitter.com/ed_howland