Forum: Ruby 2 dimensional arrays

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
4ea56c658e69eef33b6557b20c7a19ab?d=identicon&s=25 Joe Seeley (jseeley)
on 2006-05-15 23:06
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?
F3b7109c91841c7106784d229418f5dd?d=identicon&s=25 Justin Collins (justincollins)
on 2006-05-15 23:14
(Received via mailing list)
Joe Seeley 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
37a3c73ffbf864e4b28f7f2384ee12ce?d=identicon&s=25 Timothy Hunter (tim-hunter)
on 2006-05-16 00:20
(Received via mailing list)
On May 15, 2006, at 5:06 PM, Joe Seeley 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.
4ea56c658e69eef33b6557b20c7a19ab?d=identicon&s=25 Joe Seeley (jseeley)
on 2006-05-16 15:34
Timothy Hunter wrote:
> On May 15, 2006, at 5:06 PM, Joe Seeley 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.
81d609425e306219d54d793a0ad98bce?d=identicon&s=25 Matthew Moss (Guest)
on 2006-05-16 16:41
(Received via mailing list)
> 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
81d609425e306219d54d793a0ad98bce?d=identicon&s=25 Matthew Moss (Guest)
on 2006-05-16 16:42
(Received via mailing list)
> 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...
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2006-05-16 16:45
(Received via mailing list)
On Tue, 16 May 2006, Joe Seeley 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
4ea56c658e69eef33b6557b20c7a19ab?d=identicon&s=25 Joe Seeley (jseeley)
on 2006-05-16 18:08
Matthew Moss 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
4ea56c658e69eef33b6557b20c7a19ab?d=identicon&s=25 Joe Seeley (jseeley)
on 2006-05-16 18:30
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
81d609425e306219d54d793a0ad98bce?d=identicon&s=25 Matthew Moss (Guest)
on 2006-05-16 19:23
(Received via mailing list)
> 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.  ;)
This topic is locked and can not be replied to.