Problem making an array of arrays (of arrays)

Hey, bit of a ruby noob here :slight_smile:

First, hello ruby-forum community.

So, here is my problem. I want to create a 5x5 grid, however, each of
the β€˜cells’ in the grid should be able to hold a variety of values.

Firstly, I started off with this:

@row_1 = ['x','x','x','x','x']
@row_2 = ['x','x','x','x','x']
@row_3 = ['x','x','x','x','x']
@row_4 = ['x','x','x','x','x']
@row_5 = ['x','x','x','x','x']
@grid = [@row_1,@row_2,@row_3,@row_4,@row_5]

So, obviously this creates a 5x5 grid, in which each of the β€˜cells’ or
@row_1…5[1…5] == β€˜x’.

I used to just alter the string value in each cell by using:

@grid[y][x] = 'new string'

But, I ultimately want each cell to be an array… So that I can push and
pop their values as they change, and then the grid will always display
the last value in the array, by using:

@row_1 = [array.last,array1.last,array2.last,array3.last]
#etc etc etc...

My problem then is, that I have a different variable name for each of
the five points in each of the five rows.

So, the solution I really want is:

Is it possible to have a variable called, say… cellxx … Then, some
piece of code that alters the xx part of the actual variable name
itself?

Because, I’m going about implementing cell00, cell01, cell02, cell03 etc
etc each as an array and my code is getting messy.

Please is there an (easier) way, to do what I want?

Sorry for the length of this, you can tell i’m new to ruby :slight_smile: Thanks!

On Thu, Mar 18, 2010 at 6:26 PM, Cec T. [email protected]
wrote:

@row_2 = [β€˜x’,β€˜x’,β€˜x’,β€˜x’,β€˜x’]
@grid[y][x] = β€˜new string’

Sorry for the length of this, you can tell i’m new to ruby :slight_smile: Thanks!

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

Personally, I think I would opt for nested classes in this case, but if
I
understand your problem correctly, then this should do what you are
asking.

the 2d array of elements that are arrays

each currently containing it’s yx location as a string

array = [[[β€œ00”], [β€œ01”], [β€œ02”], [β€œ03”], [β€œ04”]],
[[β€œ10”], [β€œ11”], [β€œ12”], [β€œ13”], [β€œ14”]],
[[β€œ20”], [β€œ21”], [β€œ22”], [β€œ23”], [β€œ24”]],
[[β€œ30”], [β€œ31”], [β€œ32”], [β€œ33”], [β€œ34”]],
[[β€œ40”], [β€œ41”], [β€œ42”], [β€œ43”], [β€œ44”]]]

go through the array and set variables to reference the individual

cells
array.each_with_index do |row,y|
row.each_with_index do |element,x|
instance_variable_set β€œ@array#{y}#{x}” , element
end
end

show that we can access it as you describe

@array00 << β€˜a’
@array01 << β€˜b’
@array11 << β€˜c’
@array22 << β€˜d’
@array33 << β€˜e’
@array43 << β€˜f’
@array44 << β€˜g’

format the output so that it is easier to see what we did

puts β€˜[’
array.each do |row|
print ’ [ ’
row.each do |col|
printf β€˜%-12s , ’ , col.inspect
end
puts ’ ]’
end
puts β€˜]’

2010/3/19 Cec T. [email protected]:

@row_2 = [β€˜x’,β€˜x’,β€˜x’,β€˜x’,β€˜x’]
@grid[y][x] = β€˜new string’

So, the solution I really want is:

Is it possible to have a variable called, say… cellxx … Then, some
piece of code that alters the xx part of the actual variable name
itself?

Because, I’m going about implementing cell00, cell01, cell02, cell03 etc
etc each as an array and my code is getting messy.

It’s not a good idea to encode what is an index into the variable
name. Rather you should use proper indexing.

Please is there an (easier) way, to do what I want?

grid = Array.new(5) { Array.new(5) { [] } }

Now you can do

irb(main):006:0> grid[1][2]
=> []
irb(main):007:0> grid[1][2] << β€œdat”
=> [β€œdat”]
irb(main):008:0> grid[1][2]
=> [β€œdat”]
irb(main):009:0> grid[1][2] << β€œfoo”
=> [β€œdat”, β€œfoo”]
irb(main):010:0> grid[1][2]
=> [β€œdat”, β€œfoo”]

Kind regards

robert

On Mar 18, 6:26 pm, Cec T. [email protected] wrote:

So, here is my problem. I want to create a 5x5 grid, however, each of
the β€˜cells’ in the grid should be able to hold a variety of values.

rb(main):001:0> a = Array.new(5){ Array.new(5) }
=> [[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]]

irb(main):002:0> require β€˜pp’; pp a
[[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

That says:
Create an array with 5 elements; for each of the five elements, call
this block and use the return value for the value of the element. When
you call the block, create a new array of 5 empty elements.

You also can use the index of the array in your block. For example:

irb(main):009:0> CHARS = (β€˜Aβ€™β€¦β€˜Z’).to_a
=> [β€œA”, β€œB”, β€œC”, β€œD”, β€œE”, β€œF”, β€œG”, β€œH”, β€œI”, β€œJ”, β€œK”, β€œL”, β€œM”,
β€œN”, β€œO”, β€œP”, β€œQ”, β€œR”, β€œS”, β€œT”, β€œU”, β€œV”, β€œW”, β€œX”, β€œY”, β€œZ”]

irb(main):010:0> excel = Array.new(5){ |row| Array.new(5){ |col|
β€œ#{CHARS[col]}#{row+1}” } }
=> [[β€œA1”, β€œB1”, β€œC1”, β€œD1”, β€œE1”], [β€œA2”, β€œB2”, β€œC2”, β€œD2”, β€œE2”],
[β€œA3”, β€œB3”, β€œC3”, β€œD3”, β€œE3”], [β€œA4”, β€œB4”, β€œC4”, β€œD4”, β€œE4”], [β€œA5”,
β€œB5”, β€œC5”, β€œD5”, β€œE5”]]

irb(main):012:0> pp excel
[[β€œA1”, β€œB1”, β€œC1”, β€œD1”, β€œE1”],
[β€œA2”, β€œB2”, β€œC2”, β€œD2”, β€œE2”],
[β€œA3”, β€œB3”, β€œC3”, β€œD3”, β€œE3”],
[β€œA4”, β€œB4”, β€œC4”, β€œD4”, β€œE4”],
[β€œA5”, β€œB5”, β€œC5”, β€œD5”, β€œE5”]]
=> nil

So, the solution I really want is:

Is it possible to have a variable called, say… cellxx … Then, some
piece of code that alters the xx part of the actual variable name
itself?

That’s a bad solution. Programmatically create or modify your array in
loops; don’t create explicit temporary variables you don’t need.
Here’s another solution:

irb(main):013:0> a = []
=> []

irb(main):014:0> 5.times{ |i| a[i] = [] }
=> 5

irb(main):015:0> a
=> [[], [], [], [], []]

irb(main):016:0> a[2][3] = β€œhi”
=> β€œhi”

irb(main):017:0> a
=> [[], [], [nil, nil, nil, β€œhi”], [], []]