Multi-dimensional Arrays

Hi all,

I'm a Ruby noob so please forgive me...

I know there exist "simple" ways (Google's thy friend)
to create md arrays with Ruby. But it's somehow cumbersome
and it would be nice if it could be done like "array = Array.new(3,3)" -> I know too that this means not the same in Ruby...

What I like to know: what led to the decission to do it that way
and not like it is done in the C/C++ (Java) languages à la
"int[][] arr = new int[3][3]"?

Maybe because this approach is not strictly oo-oriented? But then,
switches and loops in Ruby are neither.

It's just the devil inside who likes to know about the philosophy
about the "why it is done like that" and I'm not bitching about
Ruby (by no means).

Thank you for a pointer or a short explanation.

Greetings,
Peter

Hi all,

I'm a Ruby noob so please forgive me...

I know there exist "simple" ways (Google's thy friend)
to create md arrays with Ruby. But it's somehow cumbersome
and it would be nice if it could be done like "array = Array.new(3,3)"
-> I know too that this means not the same in Ruby...

What I like to know: what led to the decission to do it that way
and not like it is done in the C/C++ (Java) languages à la
"int arr = new int[3][3]"?

you do it the same as in c, you say that you want an array of arrays.
E.g.

arr = Array.new(3) { Array.new(3) }

which is the same as int[3][3] in c where iirc int[3][3] is not a
contiguous block of memory but pointers to arrays. If you want a
contiguous block of memory maybe narray can help you.

Maybe because this approach is not strictly oo-oriented? But then,
switches and loops in Ruby are neither.

In my opinion this has nothing to do with oo versus non oo. Switches
and loops are signs of imperative programming, which is oppsite to
functional and logical programming but orthogonal to object oriented
versus not object oriented.

It's just the devil inside who likes to know about the philosophy
about the "why it is done like that" and I'm not bitching about
Ruby (by no means).

Thank you for a pointer or a short explanation.

Greetings,
Peter

And beware that
Array.new(3, Array.new(3)) is not the same as Array.new(3) { Array.new(3) }

hope to help,

Brian

···

On 11/10/05, Peter v. N. <skull2crush@hotmail.com> wrote:

--
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/

Hi --

Hi all,

I'm a Ruby noob so please forgive me...

Welcome to Ruby!

I know there exist "simple" ways (Google's thy friend)
to create md arrays with Ruby. But it's somehow cumbersome
and it would be nice if it could be done like "array = Array.new(3,3)" -> I know too that this means not the same in Ruby...

What I like to know: what led to the decission to do it that way
and not like it is done in the C/C++ (Java) languages à la
"int arr = new int[3][3]"?

Maybe because this approach is not strictly oo-oriented? But then,
switches and loops in Ruby are neither.

OK... but finding a couple of things that aren't strictly OO doesn't
mean that Ruby should just give up and make everything non-OO :slight_smile:
Each part of Ruby is carefully designed to contribute to the whole
system.

In the case of int arr... Ruby variables are always untyped. If
you can do:

   arr =

you can also do:

   arr = "I am not an array!"

The identifier 'arr' has no particular type. That's a big part of the
dynamics and dynamism of Ruby.

Also, you're assuming that means "array indexing". Actually, this:

   x

is just syntactic sugar for this:

   x. # call method ""

and you can define to do whatever you want:

   obj = Object.new

   # Define a "singleton" method for obj
   def obj.(x)
     "Are you trying to access index #{x}??"
   end

   puts obj[3] # Are you trying to access index 3??

So there's no reason to think that the notation would mean
"nested array".

There's a Matrix class, by the way, that might help you automate what
you need to do a little more.

David

···

On Tue, 11 Oct 2005, Peter v. N. wrote:

--
David A. Black
dblack@wobblini.net

Hi all,

I'm a Ruby noob so please forgive me...

I know there exist "simple" ways (Google's thy friend) to create md arrays
with Ruby. But it's somehow cumbersome and it would be nice if it could be
done like "array = Array.new(3,3)" -> I know too that this means not the
same in Ruby...

What I like to know: what led to the decission to do it that way
and not like it is done in the C/C++ (Java) languages à la
"int arr = new int[3][3]"?

this is precisely because these languages do __not__ have multi-dimensional
arrays and they muse be composed of uni-dimensional ones. ruby is the same.
the big difference is that there is no difference between compile time and
runtime in ruby so, if i could say

   a = array[3]

in ruby, then

   a = array[3][3]

would mean

   a = (the_first_array = array[3])[ index = 3]

in otherwords you'd index the first array by the second value. another issue
is that, in ruby, a declaration is the same as a definition. so, in c, you
cannot write

   printf ("%d\n", (int [42])[0]);

but in ruby you can write

   printf "%d\n", [42][0]

because you can simoultaneously define and declare an object, and this have
object, including array, literals.

Maybe because this approach is not strictly oo-oriented? But then, switches
and loops in Ruby are neither.

i thinks it's more syntax/interpreter related.

It's just the devil inside who likes to know about the philosophy about the
"why it is done like that" and I'm not bitching about Ruby (by no means).

the best reason may be that's it's so easy to setup you're own md definer:

   harp:~ > cat a.rb
   require 'pp'

   md = lambda{|*ds| Array::new(ds.shift||0).map{md[*ds] unless ds.empty?}}

   pp md
   pp md[1]
   pp md[2]
   pp md[2,3]
   pp md[2,3,4]

   harp:~ > ruby a.rb
   
   [nil]
   [nil, nil]
   [[nil, nil, nil], [nil, nil, nil]]
   [[[nil, nil, nil, nil], [nil, nil, nil, nil], [nil, nil, nil, nil]],
    [[nil, nil, nil, nil], [nil, nil, nil, nil], [nil, nil, nil, nil]]]

cheers.

-a

···

On Tue, 11 Oct 2005, Peter v. N. wrote:
--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

===============================================================================

There are several different kinds of multidimensional arrays. One is
true rectangular arrays (efficient memory allocation, bounds checked in
every dimension) - I think FISh supports those[1], and probably Matlab
as well.

Then there's C's rectangular arrays with weak (no!) bounds checking -
the array is allocated as a contiguous block, and multidimensional
indexes are converted into (computed) single dimensional offsets into
the block.

And finally, Ruby uses the lists-of-lists approach, in which you have
only one-dimensional arrays, but every cell of those arrays can be an
array itself (and so on recursively). Not as efficient as the
rectangular approach, but it allows for irregularly shaped arrays.

martin

[1] http://www-staff.it.uts.edu.au/~cbj/FISh/Announcement/

···

Peter v. N. <skull2crush@hotmail.com> wrote:

I know there exist "simple" ways (Google's thy friend)
to create md arrays with Ruby. But it's somehow cumbersome
and it would be nice if it could be done like "array = Array.new(3,3)"
-> I know too that this means not the same in Ruby...

What I like to know: what led to the decission to do it that way
and not like it is done in the C/C++ (Java) languages à la
"int arr = new int[3][3]"?

Peter v. N. wrote:

I know there exist "simple" ways (Google's thy friend)
to create md arrays with Ruby. But it's somehow cumbersome
and it would be nice if it could be done like "array = Array.new(3,3)"

require 'pp'

# Create and initialize a multi-dimensional array
# given an array of its required dimensions
# and an initial value for all cells
def ArrayFactory(dimensions, initialvalue)
   size = dimensions.first
   if dimensions.length == 1
     return Array.new(size, initialvalue)
   else
     rest = dimensions[1,dimensions.length-1]
     a = Array.new(size)
     for i in 0..size
       a[i] = ArrayFactory(rest, initialvalue)
     end
     return a
   end
end

a = ArrayFactory([3, 5, 7], "Hi!")
pp a

a[2][3][7] = "Hello!"
puts a[2][3][7]
pp a[2][3]

Or see the various enhanced Array classes on RubyForge etc.

mathew

···

--
<URL:http://www.pobox.com/~meta/&gt;
          WE HAVE TACOS

probably worth noting here that narray provides a syntheiss of both, with
copious numerical and array based methods added to boot.

cheers.

-a

···

On Wed, 12 Oct 2005, Martin DeMello wrote:

Peter v. N. <skull2crush@hotmail.com> wrote:

I know there exist "simple" ways (Google's thy friend)
to create md arrays with Ruby. But it's somehow cumbersome
and it would be nice if it could be done like "array = Array.new(3,3)"
-> I know too that this means not the same in Ruby...

What I like to know: what led to the decission to do it that way
and not like it is done in the C/C++ (Java) languages à la
"int arr = new int[3][3]"?

There are several different kinds of multidimensional arrays. One is
true rectangular arrays (efficient memory allocation, bounds checked in
every dimension) - I think FISh supports those[1], and probably Matlab
as well.

Then there's C's rectangular arrays with weak (no!) bounds checking -
the array is allocated as a contiguous block, and multidimensional
indexes are converted into (computed) single dimensional offsets into
the block.

And finally, Ruby uses the lists-of-lists approach, in which you have
only one-dimensional arrays, but every cell of those arrays can be an
array itself (and so on recursively). Not as efficient as the
rectangular approach, but it allows for irregularly shaped arrays.

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

===============================================================================

Thank you for all the replies! This is really great.

But I still wonder (or play dumb here):

what's the difference between

arr = Array.new(3) { Array.new(3) }

  and

arr = Array.new(3, Array.new(3))

Brian Schröder wrote:

···

On 11/10/05, Peter v. N. <skull2crush@hotmail.com> wrote:

Hi all,

I'm a Ruby noob so please forgive me...

I know there exist "simple" ways (Google's thy friend)
to create md arrays with Ruby. But it's somehow cumbersome
and it would be nice if it could be done like "array = Array.new(3,3)"
-> I know too that this means not the same in Ruby...

What I like to know: what led to the decission to do it that way
and not like it is done in the C/C++ (Java) languages à la
"int arr = new int[3][3]"?

you do it the same as in c, you say that you want an array of arrays.
E.g.

arr = Array.new(3) { Array.new(3) }

which is the same as int[3][3] in c where iirc int[3][3] is not a
contiguous block of memory but pointers to arrays. If you want a
contiguous block of memory maybe narray can help you.

Maybe because this approach is not strictly oo-oriented? But then,
switches and loops in Ruby are neither.

In my opinion this has nothing to do with oo versus non oo. Switches
and loops are signs of imperative programming, which is oppsite to
functional and logical programming but orthogonal to object oriented
versus not object oriented.

It's just the devil inside who likes to know about the philosophy
about the "why it is done like that" and I'm not bitching about
Ruby (by no means).

Thank you for a pointer or a short explanation.

Greetings,
Peter

And beware that
Array.new(3, Array.new(3)) is not the same as Array.new(3) { Array.new(3) }

hope to help,

Brian

--
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/

Hi --

Thank you for all the replies! This is really great.

But I still wonder (or play dumb here):

what's the difference between

arr = Array.new(3) { Array.new(3) }

  and

arr = Array.new(3, Array.new(3))

In the first one, the block is executed once each time to fill up the
array. It's like:

   arr = [Array.new(3),Array.new(3),Array.new(3)]

So it's an array of three different arrays.

The second one sets all three initial values to the *same* array.
It's like:

   inner = Array.new(3)
   arr = [inner,inner,inner]

So you've got an array of three copies of the same object, which of
course has major implications when you modify that object, etc.

David

···

On Wed, 12 Oct 2005, Peter v. N. wrote:

--
David A. Black
dblack@wobblini.net

I got that! Your explanation is clear & simple.

I'm really astonished as how fast everyone responds here.

Thank you all..and wait for more to come from my side :wink:

David A. Black wrote:

···

Hi --

On Wed, 12 Oct 2005, Peter v. N. wrote:

Thank you for all the replies! This is really great.

But I still wonder (or play dumb here):

what's the difference between

arr = Array.new(3) { Array.new(3) }

    and

arr = Array.new(3, Array.new(3))

In the first one, the block is executed once each time to fill up the
array. It's like:

  arr = [Array.new(3),Array.new(3),Array.new(3)]

So it's an array of three different arrays.

The second one sets all three initial values to the *same* array.
It's like:

  inner = Array.new(3)
  arr = [inner,inner,inner]

So you've got an array of three copies of the same object, which of
course has major implications when you modify that object, etc.

David