Nooby question : multidimensional arrays

Well am I right, that in Ruby there are only one dimensional arrays, and that i have to add an array into an array to get multidimensional arrays, or is there a simpler more ruby like way to create them ?

Yep. You create them by just making arrays of arrays and you reference them just like C arrays
irb(main):001:0> ary =
=>
irb(main):002:0> ary << [1, 2, 3] << %w{dog cat bird} << [8, 10, 17]
=> [[1, 2, 3], ["dog", "cat", "bird"], [8, 10, 17]]
irb(main):003:0> ary[1][2]
=> "bird"

···

On Aug 16, 2006, at 2:37 AM, marinho.tobolla@syncity.de wrote:

Well am I right, that in Ruby there are only one dimensional arrays, and that i have to add an array into an array to get multidimensional arrays, or is there a simpler more ruby like way to create them ?

--
The folly of mistaking a paradox for a discovery, a metaphor for a proof, a torrent of verbiage for a spring of capital truths, and oneself for an oracle, is inborn in us.
-Paul Valery, poet and philosopher (1871-1945)

"marinho.tobolla@syncity.de" <marinho.tobolla@syncity.de> writes:

Well am I right, that in Ruby there are only one dimensional arrays,
and that i have to add an array into an array to get
multidimensional arrays, or is there a simpler more ruby like way to
create them ?

Well, there's also the block that Array.new takes to give its initial
value:

a = Array.new(8) {Array.new(8) {0}}

This creates an 8 by 8 two-dimensional array initialized with all 0.

(Technically, you don't need that second block and could do the inner
bit as Array.new(8,0))

Well am I right, that in Ruby there are only one dimensional arrays, and that i have to add an array into an array to get multidimensional arrays, or is there a simpler more ruby like way to create them ?

Others have given you great answers, but it's also worth pointing out that you can make a multidimensional Array, if you like:

>> class Array2D
>> def initialize(width, height)
>> @data = Array.new(width) { Array.new(height) }
>> end
>> def (x, y)
>> @data[y]
>> end
>> def =(x, y, value)
>> @data[y] = value
>> end
>> end
=> nil
>> arr = Array2D.new(3, 2)
=> #<Array2D:0x31d0b0 @data=[[nil, nil], [nil, nil], [nil, nil]]>
>> arr[1, 1] = "Hello"
=> "Hello"
>> arr
=> #<Array2D:0x31d0b0 @data=[[nil, nil], [nil, "Hello"], [nil, nil]]>
>> arr[1, 1]
=> "Hello"

James Edward Gray II

···

On Aug 16, 2006, at 4:37 AM, marinho.tobolla@syncity.de wrote:

Or, if you need a speed burst, NArray [http://narray.rubyforge.org/\]
could help. Never used it myself yet though.

David Vallner

···

On Wed, 2006-08-16 at 18:37 +0900, marinho.tobolla@syncity.de wrote:

Well am I right, that in Ruby there are only one dimensional arrays, and that i have to add an array into an array to get multidimensional arrays, or is there a simpler more ruby like way to create them ?

Is this an okay job of implementing a multidimensional array?

Thank you for any feedback.

-Kedar

···

--
Posted via http://www.ruby-forum.com/.

Larry,

Thanks for references and detailed review. I will go over them to
understand them better. Just to reiterate, my implementation is pretty
rudimentary at this point and more importantly, it caters for the cases
where the number of elements in *every dimension* is assumed to be the
same (IOW, you can't simply represent a 2x3 matrix is it).

-Kedar

···

--
Posted via http://www.ruby-forum.com/.

I know this is an old thread, but I have to respond since the venerable
JEGII didn't point out the obvious to you guys.

Matrix.build(row_count, col_count) do |row, col|

end

See
http://www.ruby-doc.org/stdlib/libdoc/matrix/rdoc/classes/Matrix.html

···

--
Posted via http://www.ruby-forum.com/.

One would have to think in Ruby. For a C programmer, it can be a hard transition but once one gets used to the Ruby way, you will find the C way bit inflexible and rigid. For example, in C, you might write:

#define NUM_COLS 20
#define NUM_ROWS 10
int ary[NUM_ROWS][NUM_COLS];
...
int i, j;
for (i = 0; i < NUM_ROWS; i++) {
    for (j = 0; i < NUM_COLS; j++) {
        ary[i][j] = some_code....
   }
}

In Ruby, you don't need to worry about setting up iterator variables since arrays know how to iterate themselves, e.g.

ary.each {|r|
    r.each {|c|
        ...
    }
}

If you need to access a specific element, you can still use the C-like notation, i.e. ary[r][c].

···

----- Original Message ----- From: "Chris Gehlker" <canyonrat@mac.com>

On Aug 16, 2006, at 2:37 AM, marinho.tobolla@syncity.de wrote:

Well am I right, that in Ruby there are only one dimensional arrays, and that i have to add an array into an array to get multidimensional arrays, or is there a simpler more ruby like way to create them ?

Yep. You create them by just making arrays of arrays and you reference them just like C arrays
irb(main):001:0> ary =
=>
irb(main):002:0> ary << [1, 2, 3] << %w{dog cat bird} << [8, 10, 17]
=> [[1, 2, 3], ["dog", "cat", "bird"], [8, 10, 17]]
irb(main):003:0> ary[1][2]
=> "bird"

--
The folly of mistaking a paradox for a discovery, a metaphor for a proof, a torrent of verbiage for a spring of capital truths, and oneself for an oracle, is inborn in us.
-Paul Valery, poet and philosopher (1871-1945)

01 class Array2D
02
03 def initialize(width, height)
04 @data = Array.new(width) { Array.new(height) }
05 end
06
07 def [](x, y)
08 @data[x][y]
09 end
10
11 def []=(x, y, value)
12 @data[x][y] = value
13 end
14
15 end

Can someone explain what's going on in this code for a newbie.

I'm getting lost in the looping logic of the second def; and the 3rd def
I'm guessing has something do do with hashes?

I'm using this code in a simple 2d array. It was working but then I
changed all of my ranges from (0...value) to (1..value) [I used ranges
to populate my 2D array with hashes] I now get the error message:

11:in `[]=': undefined method `[]=' for nil:NilClass (NoMethodError)

···

--
Posted via http://www.ruby-forum.com/.

uhm...i'm not sure what your trying to do with this, but what if i wanted to
get the 5th element in the 4th dimension?

i'd write the generator method something like this:

while i < @n
j = 0
while j < @m
@array[[i]] << 0
j += 1
end
i += 1
end

(i havnt tested it, so it may not work)

then you'd need to define the other accessor methods & such... but thats a
start

hex

···

On Fri, Jan 7, 2011 at 6:56 PM, Kedar Mhaswade <kedar.mhaswade@gmail.com>wrote:

Is this an okay job of implementing a multidimensional array?

datacube/data_cube.rb at master · kedarmhaswade/datacube · GitHub

Thank you for any feedback.

-Kedar

--
Posted via http://www.ruby-forum.com/\.

There's a book:

  An APL Compiler

which describes an expansion vector which is a scan of
the array sizes. IOW, for:

  arr = Array.new(s0,s1,...sn)

the expansion vector for this arr is:

  arr.ev = [1, s0, s0*s1, s0*s1*s3,..., s0*s1*...*sn]

The i-th element of arr.ev is the distance between successive
elements in the i-th dimension. IOW:

  the locatoin of:
    arr[i0,i1,..., ij, ... in]
  is located arr.ev[j] elements from:
    arr[i0,i1,..., ij+1, ... in]

IOW:

    arr[i0,i1,..., ij, ... in]

is located:

    i0*arr.ev[0]+i1*arr.ev[1]+...+in*arr.ev[n]

elements from the 1st element:

    arr[0,0,...,0]

Thus, given the sizes, you can create a member variable
which is the expansion vector, then use that to access the
elements by calculating the offset from the initial element
using the dot product:

    i0*arr.ev[0]+i1*arr.ev[1]+...+in*arr.ev[n]

HTH.

Good luck.

···

On 01/07/11 17:56, Kedar Mhaswade wrote:

Is this an okay job of implementing a multidimensional array?

datacube/data_cube.rb at master · kedarmhaswade/datacube · GitHub

Thank you for any feedback.

-Kedar

If you need that you could do something like https://gist.github.com/772827

Cheers

robert

···

On Mon, Jan 10, 2011 at 2:06 PM, Kedar Mhaswade <kedar.mhaswade@gmail.com> wrote:

Thanks for references and detailed review. I will go over them to
understand them better. Just to reiterate, my implementation is pretty
rudimentary at this point and more importantly, it caters for the cases
where the number of elements in *every dimension* is assumed to be the
same (IOW, you can't simply represent a 2x3 matrix is it).

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Kadar,

I was looking through my computers ruby packages and found one:

  libnarray-ruby1.9.1

claiming it:

  has numerical n-dimensional array class

Googling found:

  Tentative NArray Tutorial · princelab/narray Wiki · GitHub

So, I tried it and, it works:

/home/evansl/prog_dev/ruby $ irb1.9.1
irb(main):001:0> require 'narray'
=> true
irb(main):002:0> a = NArray.int(2,3,4)
=> NArray.int(2,3,4):
[ [ [ 0, 0 ],
    [ 0, 0 ],
    [ 0, 0 ] ],
  [ [ 0, 0 ],
    [ 0, 0 ],
    [ 0, 0 ] ],
  [ [ 0, 0 ],
    [ 0, 0 ],
    [ 0, 0 ] ],
  [ [ 0, 0 ],
...
irb(main):003:0>

HTH.

-Larry

···

On 01/10/11 07:06, Kedar Mhaswade wrote:

Larry,

Thanks for references and detailed review. I will go over them to
understand them better. Just to reiterate, my implementation is pretty
rudimentary at this point and more importantly, it caters for the cases
where the number of elements in *every dimension* is assumed to be the
same (IOW, you can't simply represent a 2x3 matrix is it).

-Kedar

The first method simply creates an Array of size width and places an Array of size height in each index, so

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

The second method is merely a way of accessing a coordinate within the 2d array, so for
a = Array2D.new 2, 2
a[0,1]

it would first find @data[0] which would return the object in index 0 which is an array [ nil, nil ] and then @data[0][1] would return the object in index 1 of the sub-array which in this case is nil. In fact the logic here is no more complex than the logic for a simple Array... it only looks more complex, because we are using the same method twice... perhaps it'd help to think about it like this

def (x, y)
   sub_array = @data
   return sub_array[y]
end

The third def is exactly the same as the second def, except instead of simply looking to see what's stored at a coordinate, you're changing the object that's stored at that coordinate. Again the logic is the same as with simple arrays, except the object in each index is also an array.

I don't know exactly what's causing the error you're seeing, but it looks like you're calling [x,y]= using a value of x that is higher than the maximum index in the outer array, so instead of returning a sub_array it returns nil, and then tries to call [y]= on nil...

hth...

···

On 12 Sep 2009, at 11:06, Shawn W_ wrote:

01 class Array2D
02
03 def initialize(width, height)
04 @data = Array.new(width) { Array.new(height) }
05 end
06
07 def (x, y)
08 @data[y]
09 end
10
11 def =(x, y, value)
12 @data[y] = value
13 end
14
15 end

Can someone explain what's going on in this code for a newbie.

I'm getting lost in the looping logic of the second def; and the 3rd def
I'm guessing has something do do with hashes?

I'm using this code in a simple 2d array. It was working but then I
changed all of my ranges from (0...value) to (1..value) [I used ranges
to populate my 2D array with hashes] I now get the error message:

11:in `=': undefined method `=' for nil:NilClass (NoMethodError)
--
Posted via http://www.ruby-forum.com/\.

04 @data = Array.new(width) { Array.new(height) }

Create an Array named @data initially with 'width' rows. Set the value of each element of the array to a new array with 'height' rows.

If 'width' is 3 and 'height' is 2, @data initially looks like:

[[nil, nil], [nil, nil], [nil, nil]]

07 def (x, y)
08 @data[y]
09 end

Create a method to access the elements like so:

obj[2,0] returns the value of @data[2][0] (here it would be nil)

11 def =(x, y, value)
12 @data[y] = value
13 end

Create a method to set the values:

obj[1,1] = 4 assigns 5 to the array element at of @data[1][1]

After which, @data would look like:

[[nil, nil], [nil, 5], [nil, nil]]

I'm not sure what looping logic you're talking about. There are no loops here, nor any hashes. Array access syntax looks the same as hashes. If you think there are hashes because of the block braces { }, it's an unfortunate thing that they share the same syntax, but generally whether it's a block or an array is pretty clear from the context.

Basically all that's going on is that this class is creating a way of doing 2d arrays with a subscript that looks like [x, y], and hiding the fact that the underlying implementation is actually a 1 dimensional array containing at each element another one-dimensional array.

I'm using this code in a simple 2d array. It was working but then I
changed all of my ranges from (0...value) to (1..value) [I used ranges
to populate my 2D array with hashes] I now get the error message:

What's probably happening is that you're going beyond the initial size of the array (width, height). If your array is 2 by 3 and you try to do:

x[10, 20] = 5

Internally it tries to do @data[10][20] = 5. @data[10] is past the end of the array, so its value is nil, so @data[10][20] = 5 becomes nil[20] = 5.

Giving the error message:

11:in `=': undefined method `=' for nil:NilClass (NoMethodError)

You could probably fix that by changing the = method to something like:

def =(x, y, value)
   # If @data is nil, create it as an empty array
   @data ||= Array.new
   @data[y] = value
end

If you do that, you should also fix to create missing values too:

def (x, y)
   # If @data is nil, create it as an empty array
   @data ||= Array.new
   @data[y]
end

Ben

···

On Sep 12, 2009, at 00:06, Shawn W_ wrote:

Thanks for the feedback!

I simply thought it would be nice if you can address elements simply as:
A[i, j, k ...]

uhm...i'm not sure what your trying to do with this, but what if i
wanted to
get the 5th element in the 4th dimension?

Wouldn't that simply be dc[0,0,0,5]?

···

i'd write the generator method something like this:

while i < @n
j = 0
while j < @m
@array[[i]] << 0
j += 1
end
i += 1
end

(i havnt tested it, so it may not work)

then you'd need to define the other accessor methods & such... but
thats a
start

hex

--
Posted via http://www.ruby-forum.com/\.

[snip]

Thus, given the sizes, you can create a member variable
which is the expansion vector, then use that to access the
elements by calculating the offset from the initial element
using the dot product:

    i0*arr.ev[0]+i1*arr.ev[1]+...+in*arr.ev[n]

Also, if you're interested in transposing the vector,
IIRC, that just invovles permuting the expansion vector.
IOW, if the original expansion vector was:

  evo = [e1,e2,e3,...,en-1,en]

then simply reversing it:

  evt = [en,en-1,....,e3,e2,e1]

and using the same vector of values for elements,
would result in a transposed array. I guess you
could try that for just 2 dimensional array
to see if that works.

  -Larry

···

On 01/07/11 21:57, Larry Evans wrote:

Is this an okay job of implementing a multidimensional array?

datacube/data_cube.rb at master · kedarmhaswade/datacube · GitHub

Thank you for any feedback.

-Kedar

There's a book:

  An APL Compiler

which describes an expansion vector which is a scan of
the array sizes. IOW, for:

  arr = Array.new(s0,s1,...sn)

the expansion vector for this arr is:

  arr.ev = [1, s0, s0*s1, s0*s1*s3,..., s0*s1*...*sn]

The expansion vector for DataCube.new(n,m) would be:

  [m**0,m**1,m**2,...,m**n]

IOW, the length of this expansion vector is n+1.

[snip]

    arr[i0,i1,..., ij, ... in]

is located:

    i0*arr.ev[0]+i1*arr.ev[1]+...+in*arr.ev[n]

elements from the 1st element:

    arr[0,0,...,0]

Thus, given the sizes, you can create a member variable
which is the expansion vector, then use that to access the
elements by calculating the offset from the initial element
using the dot product:

    i0*arr.ev[0]+i1*arr.ev[1]+...+in*arr.ev[n]

However, after looking at:

  datacube/data_cube.rb at master · kedarmhaswade/datacube · GitHub

it's not clear that to_index calculates the same offset because
coefficients[i] corresponds to one of the i0,i1,...,in-1 in the
above formulat, and coefficients[i] is not multiplied by anything.
It's only added to mega_index*n, and mega_index*n involves
multiplication by the dimension, n, instead of ths uniform size, m.

HTH

  -Larry

···

On 01/07/11 21:57, Larry Evans wrote:

On 01/07/11 17:56, Kedar Mhaswade wrote:

If you need that you could do something like
Multi Dimensional Array · GitHub

Cheers

robert

Interesting. Thanks, Robert.
But using hash internally to represent arrays is slightly
counterintuitive. But I agree, it will work well for "sparse"
multi-dimensional arrays. I realize that I could do something similar
and still retain the one-dimensional flattening, in my implementation.
And yes, expanding it to do non-cube entities is on my list.

-Kedar

···

--
Posted via http://www.ruby-forum.com/\.