2 dimensional arrays

The 2 dimensional array or table structure is extremely common, but I
don’t see a simple/standard way to implement this in Ruby. Is there an
easy way to do this?

Joe S. wrote:

The 2 dimensional array or table structure is extremely common, but I
don’t see a simple/standard way to implement this in Ruby. Is there an
easy way to do this?

One pretty easy way:

irb(main):001:0> a = [ [1, 2, 3] ]
=> [[1, 2, 3]]
irb(main):002:0> a[0]
=> [1, 2, 3]
irb(main):003:0> a[0][1]
=> 2

-Justin

On May 15, 2006, at 5:06 PM, Joe S. wrote:

The 2 dimensional array or table structure is extremely common, but I
don’t see a simple/standard way to implement this in Ruby. Is
there an
easy way to do this?


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

A 2-dimensional array is simply an array of arrays. Something like this:

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

Or you could use the Matrix class from “matrix” in the standard library.

Timothy H. wrote:

On May 15, 2006, at 5:06 PM, Joe S. wrote:

The 2 dimensional array or table structure is extremely common, but I
don’t see a simple/standard way to implement this in Ruby. Is
there an
easy way to do this?


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

A 2-dimensional array is simply an array of arrays. Something like this:

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

Or you could use the Matrix class from “matrix” in the standard library.

A 2 dimensional array as an array of arrays is a lowest common
denominator. It assumes that I want only to use it as a simple storage
mechanism. What I want is a 2 dimensional array data structure that has
powerful operating mechanisms such as sorting. Additionally the way an
array of arrays is treated in Ruby goes against what is intuitive or
expected; and it was my understanding that Ruby was supposed to be
designed to do what “least surprises”.

Here is a simple example.

a = Array.new(){Array.new()}
b = [9,8,7]
c = [1,2,3]
a[0] = b
a[1] = c

puts a.sort
=>[[1,2,3],[9,8,7]]

So this allows a sort across the entire array and it should be noted
that it does an index step through comparison so [1,1,2] would come
after [1,1,1]. However this means I am limited to sorting only via this
mechanism.

Based on Ruby syntax I would find this to be intuitive.

a[0…1][0].sort

The results I would then expect would be
[[1],[9]]

The results I actually get from this are
[7,8,9]

What is happening is that in a[0…1][0] a[0…1] is grabbing the subset
of arrays 0 to 1 and then the second index [0] is indexing back in to
the subset. What looks like it should be happening is that a[0…1][0]
is defining the set of the arrays where we wish to retrieve the 0 index.

A 2 dimensional array as an array of arrays is a lowest common
denominator. It assumes that I want only to use it as a simple storage
mechanism.

Aside from a 1-dimensional array using flattened indices, an array of
arrays is the most basic and common mechanism, because memory is
1-dimensional. Show me a computer with 2-dimensional memory and I’ll
write you a better structure.

What I want is a 2 dimensional array data structure that has
powerful operating mechanisms such as sorting. Additionally the way an
array of arrays is treated in Ruby goes against what is intuitive or
expected; and it was my understanding that Ruby was supposed to be
designed to do what “least surprises”.

I think most people find the array of arrays to be fairly intuitive
(i.e. first index selects a subarray, second index selects an item
from the subarray), and Ruby holds to that intuition. I would
nonoffensively suggest that what you are expecting is non-intuitive.

So this allows a sort across the entire array and it should be noted
that it does an index step through comparison so [1,1,2] would come
after [1,1,1]. However this means I am limited to sorting only via this
mechanism.

You are limited to that sorting mechanism only if you choose to be;
try using sort_by and use your own code to determine sort order.

Based on Ruby syntax I would find this to be intuitive.

a[0…1][0].sort

The results I would then expect would be
[[1],[9]]

The results I actually get from this are
[7,8,9]

a[0…1] grabs the 0th and 1st item of a. However, in order to return
multiple values, Ruby uses arrays, so those go right back into an
array. Then you use [0], and get back the 0th item [7,8,9]. Pretty
straightforward.

To get the results you want is not terribly difficult: a.collect {
|x| [x[0]] }

Yes, I’ve also heard that Ruby is intended to be a language of “least
surprises”, but you can satisfy everyone at the same time. However, it
is also a language of easy extendability, so if an array of arrays
does not serve your purposes, or you have a different interpretation
of the [] operator, it’s trivial to start fleshing out your own
classes to make it a language of “least surprises for you”.

class Array2D
def [] (i)
# …
end
def []= (i, x)
# …
end
end

Yes, I’ve also heard that Ruby is intended to be a language of “least
surprises”, but you can satisfy everyone at the same time.

Ummm… I think I meant you CAN’T satisfy everyone at the same time…

On Tue, 16 May 2006, Joe S. wrote:

A 2 dimensional array as an array of arrays is a lowest common denominator.
It assumes that I want only to use it as a simple storage mechanism. What I
want is a 2 dimensional array data structure that has powerful operating
mechanisms such as sorting. Additionally the way an array of arrays is
treated in Ruby goes against what is intuitive or expected; and it was my
understanding that Ruby was supposed to be designed to do what “least
surprises”.

that is widely understood to mean ‘least suprise to matz’. fyi.

So this allows a sort across the entire array and it should be noted
that it does an index step through comparison so [1,1,2] would come
after [1,1,1]. However this means I am limited to sorting only via this
mechanism.

no, it doesn’t:

harp :~ > cat a.rb

m = [9,8,7], [1,2,3]

p m.sort_by{|row| row.last}

p m.sort{|a,b| a[2] <=> b[2]}

harp :~ > ruby a.rb
[[1, 2, 3], [9, 8, 7]]
[[1, 2, 3], [9, 8, 7]]

What is happening is that in a[0…1][0] a[0…1] is grabbing the subset
of arrays 0 to 1 and then the second index [0] is indexing back in to
the subset. What looks like it should be happening is that a[0…1][0]
is defining the set of the arrays where we wish to retrieve the 0 index.

i understand why you might think that - but it doesn’t really make
sense. if
what you said were true then this

p a[1][1] #=> 2

would print an array and not 2. in otherwords if you want the last
index on a
2d array to return a column vector then access the elements would always
require 3 indices! eg. you’d need

p a[1][1][1] #=> 2

and that would be strange indeed. in addition column wise read access
requires column wise write access so one would be able to do

a[0…1][0] = a_new_column

again, requiring tripple indices to assign elements.

i think you are looking for something like narray, which is on rubyforge
and
quite powerful. it supports n-dimensional arrays with compound
indicies:

harp:~ > cat a.rb
require ‘narray’

short-cuts

 t, f = true, false

setup 2x3 array

 na = NArray.int 2, 3
 p na

row-size access

 p na[t, 0]
 na[t, 0] = 1
 p na[t, 0]
 p na

column-wise access

 p na[0, t]
 na[0, t] = 2
 p na[0, t]
 p na

element-wise access

 p na[1,2]
 na[1,2] = 42
 p na[1,2]
 p na

many operators are defined

 p na[t,2].sort
 p na[0,t].sort
 p na.min
 p na.max
 p na.mean
 p na[(na > 1).where]

harp:~ > ruby a.rb
NArray.int(2,3):
[ [ 0, 0 ],
[ 0, 0 ],
[ 0, 0 ] ]
NArray.int(2):
[ 0, 0 ]
NArray.int(2):
[ 1, 1 ]
NArray.int(2,3):
[ [ 1, 1 ],
[ 0, 0 ],
[ 0, 0 ] ]
NArray.int(3):
[ 1, 0, 0 ]
NArray.int(3):
[ 2, 2, 2 ]
NArray.int(2,3):
[ [ 2, 1 ],
[ 2, 0 ],
[ 2, 0 ] ]
0
42
NArray.int(2,3):
[ [ 2, 1 ],
[ 2, 0 ],
[ 2, 42 ] ]
NArray.int(2):
[ 2, 42 ]
NArray.int(3):
[ 2, 2, 2 ]
0
42
8.16666666666667
NArray.int(4):
[ 2, 2, 2, 42 ]

regards.

-a

Matthew M. wrote:

A 2 dimensional array as an array of arrays is a lowest common
denominator. It assumes that I want only to use it as a simple storage
mechanism.

Aside from a 1-dimensional array using flattened indices, an array of
arrays is the most basic and common mechanism, because memory is
1-dimensional. Show me a computer with 2-dimensional memory and I’ll
write you a better structure.

That is really besides the point. There are many different types of
data structures that are intended for a variety of purposes. They
abstract away from the physical layer to make things happen more easily
and intuitively in different contexts. The table is a perfect example
since that provides the type of power I want; however I am only looking
for only fraction of that power on a very dynamic and very small set of
data so creating a database would be overkill. And if you think that
having one dimensional memory limits us from having fast 2 dimensional
data structures then you really need to take some time to better
understand how some of these data structures trade memory usage for
efficiency. Try taking a look out the chunk file format, Lua’s core
table data structure, or how tables typically work in databases.

What I want is a 2 dimensional array data structure that has
powerful operating mechanisms such as sorting. Additionally the way an
array of arrays is treated in Ruby goes against what is intuitive or
expected; and it was my understanding that Ruby was supposed to be
designed to do what “least surprises”.

I think most people find the array of arrays to be fairly intuitive
(i.e. first index selects a subarray, second index selects an item
from the subarray), and Ruby holds to that intuition. I would
nonoffensively suggest that what you are expecting is non-intuitive.

I agree that it is intuitive when you are selecting a single array with
the first index. a[0] returns [7,8,9] and a[0][0] returns 7. That is
not surprising. What is less intuitive is a[0…1][x]. I’m sure it can
be argued either way and I agree that you can’t satisfy everyone.

So this allows a sort across the entire array and it should be noted
that it does an index step through comparison so [1,1,2] would come
after [1,1,1]. However this means I am limited to sorting only via this
mechanism.

You are limited to that sorting mechanism only if you choose to be;
try using sort_by and use your own code to determine sort order.

Based on Ruby syntax I would find this to be intuitive.

a[0…1][0].sort

The results I would then expect would be
[[1],[9]]

The results I actually get from this are
[7,8,9]

a[0…1] grabs the 0th and 1st item of a. However, in order to return
multiple values, Ruby uses arrays, so those go right back into an
array. Then you use [0], and get back the 0th item [7,8,9]. Pretty
straightforward.

To get the results you want is not terribly difficult: a.collect {
|x| [x[0]] }

Yes, I’ve also heard that Ruby is intended to be a language of “least
surprises”, but you can satisfy everyone at the same time. However, it
is also a language of easy extendability, so if an array of arrays
does not serve your purposes, or you have a different interpretation
of the [] operator, it’s trivial to start fleshing out your own
classes to make it a language of “least surprises for you”.

It is not “trivial” to implement all classes. Some classes are actually
quite complex and time consuming to implement. The point in my post was
to see if there was currently a “standard” class already in use today.
For more mature languages these types of structures already exist. I
enjoy using the Ruby language and find that it certain situations it is
better than other languages, but I am loathe to reinvent the wheel or
roll my own for something that I know other people use as well so it may
well exist already.

class Array2D
def [] (i)
# …
end
def []= (i, x)
# …
end
end

unknown wrote:

that is widely understood to mean ‘least suprise to matz’. fyi.

I was using that a little tongue in cheek.

So this allows a sort across the entire array and it should be noted
that it does an index step through comparison so [1,1,2] would come
after [1,1,1]. However this means I am limited to sorting only via this
mechanism.

no, it doesn’t:

harp :~ > cat a.rb

m = [9,8,7], [1,2,3]

p m.sort_by{|row| row.last}

p m.sort{|a,b| a[2] <=> b[2]}

harp :~ > ruby a.rb
[[1, 2, 3], [9, 8, 7]]
[[1, 2, 3], [9, 8, 7]]

I have not looked much at how sort_by is used, but I do see how that can
be beneficial in some situations. When I stated “such as sorting” above
that was just one example; I see that I should have given others since
the sorting piece is apparently available. I am really looking for
flexibility somewhat similar to a database table but on small dynamic
sets of data.

What is happening is that in a[0…1][0] a[0…1] is grabbing the subset
of arrays 0 to 1 and then the second index [0] is indexing back in to
the subset. What looks like it should be happening is that a[0…1][0]
is defining the set of the arrays where we wish to retrieve the 0 index.

i understand why you might think that - but it doesn’t really make
sense. if
what you said were true then this

p a[1][1] #=> 2

would print an array and not 2. in otherwords if you want the last
index on a
2d array to return a column vector then access the elements would always
require 3 indices! eg. you’d need

p a[1][1][1] #=> 2

I was saying that the syntax to include multiple rows a[n…m] was
handled differently than indexing a single row a[n]. How it was doing
this was just a conjecture based on the results.

and that would be strange indeed. in addition column wise read access
requires column wise write access so one would be able to do

a[0…1][0] = a_new_column

again, requiring tripple indices to assign elements.

i think you are looking for something like narray, which is on rubyforge
and
quite powerful. it supports n-dimensional arrays with compound
indicies:

I will check out narray to see if it fits my needs. Thanks for your
response.

-joe

regards.

-a

That is really besides the point. There are many different types of
data structures that are intended for a variety of purposes. They
abstract away from the physical layer to make things happen more easily
and intuitively in different contexts. The table is a perfect example
since that provides the type of power I want; however I am only looking
for only fraction of that power on a very dynamic and very small set of
data so creating a database would be overkill.

My point (too obvious to be stated, I thought) was that everything is
built up from the simpler. If array of arrays doesn’t do it for ya,
then you’ll need to write it yourself or find someone else who has
written what you need.

Someone suggested narray… Haven’t used it myself, so I can’t speak
for it. Someone else also mentioned the standard Matrix, which as far
as I’ve seen isn’t any more useful than an array of arrays unless
you’re using them as mathematical matrices.

It is not “trivial” to implement all classes.

That, I suppose, depends on the classes and the implementor. :wink: