How to initialize a 2 dimension array ?

Monkey Forums/Monkey Programming/How to initialize a 2 dimension array ?

Rushino(Posted 2012) [#1]
Hi there,

I have a class with a field such :

Field data:T[][] 	' The internal representation of the grid.


And then i want to initialize the data array in the constructor. But i dunno how to do that. I though it was :

Self.data = New T:[width][height]


But it doesnt seem to work. I suspect the "New T" to not working in Monkey. T is a generic. Any ideas ?

Thanks!


Rushino(Posted 2012) [#2]
I think i found the solution.

Self.data =[New T[width], New T[height]]



therevills(Posted 2012) [#3]
You could try this:

[monkeycode] 'summary: init a 2d array
Function CreateArray:T[][](rows:Int, cols:Int)
Local a:T[][] = New T[rows][]
For Local i:Int = 0 Until rows
a[i] = New T[cols]
End
Return a
End[/monkeycode]


Rushino(Posted 2012) [#4]
Yeah however this would require a loop. The idea was to get the array ready when the grid is built.

However, i will use your exemple for a grid reset method.

Thanks! :)


Jesse(Posted 2012) [#5]
however your post no 2 will not give you the results you are looking for. :)

[edit]

that example will produce an array with two columns. one column of length "width" and the other of length "height".


golomp(Posted 2012) [#6]
I have already answer to a similar post but it was not with a constructor.
but sometime simple solution are good one.


matty(Posted 2012) [#7]
Or just use a single dimensioned array and calculate the x/y position manually:


Local width:int = 7 'examples
Local height:Int = 5 'examples
Local myarray:Int[width * height]

Local index:int
Local x:int
Local y:int

'assuming a particular x/y coordinate in the grid where x/y go from 0 to width-1, height-1

index = x + y * width

'and to go back from the index to an x/y coordinate:

x = index mod width
y = (index - x) / width






Gerry Quinn(Posted 2012) [#8]
Multi-dimensional arrays in Monkey require a loop whether you like it or not.

A 2D array is a 'thing' (it's not exactly an object, but it must be 'constructed' like one) that contains a collection of 1D arrays, each of which must be individually 'constructed'. Then each 1D array contains a collection of whatever you wanted to put in your array. If those are objects (as distinct from primitives like ints) they must be constructed too.

So loops are more-or-less inescapable. Making a template like therevills suggests above is the best approach. [Depending on what you are planning, you might want to construct the individual objects too - the code above generates an array of nulls.]


Rushino(Posted 2012) [#9]
I know they require a loop but for initialization i think it is a bit overkill.

I mean what wrong with :

Field data:T[][] = New T:[width][height]


I think it do exactly what its supposed to do which is initialize an array of array of T. The result gonna be.. if you take this code :

Field data:T[][] = New T:[4][4]


The result are :

[0][1][2][3][4]
^ ^ ^ ^ ^
[0][0][0][0][0]
[1][1][1][1][1]
[2][2][2][2][2]
[3][3][3][3][3]
[4][4][4][4][4]

That why i see the first array as the width then the other array as the height.

So if your doing data[1][2] You get the second col and the third row (since its based on 0)

Local myarray:Int[width * height]


Is the same thing as my exemple. (See http://stackoverflow.com/questions/1242705/performance-of-2-dimensional-array-vs-1-dimensional-array) its just that i find the 2D array a bit less confusing when it come to indexing that is when you talk about a grid.


Rushino(Posted 2012) [#10]

however your post no 2 will not give you the results you are looking for. :)

[edit]

that example will produce an array with two columns. one column of length "width" and the other of length "height".


Why ? Sorry but i believe it actually do exactly what im looking for. :) it is initializing the first array as an array of T of width in size then for the second array an array of T of height in size. Which is perfect for the representation of a grid. (Well at least to me)


Samah(Posted 2012) [#11]
Why ? Sorry but i believe it actually do exactly what im looking for. :) it is initializing the first array as an array of T of width in size then for the second array an array of T of height in size. Which is perfect for the representation of a grid. (Well at least to me)

The number of elements in a grid is width*height. What you have done is to create enough elements for width PLUS height. A loop is the best way to generate a grid structure in an array-of-arrays situation.

Personally I tend to avoid them altogether; just create a [width*height] array and index it with (x+y*width).

Additional: Monkey does not have "multi-dimensional arrays", it has "arrays of arrays". There's a big difference.


Shinkiro1(Posted 2012) [#12]
In monkey, if you want to create a 2 dimensional array, you will have to do it with a function like therevills posted.
Even Mark Sibly, the creator monkey suggested to do it that way, he should know it best.

What is it that you don't like about the solution offered?


Gerry Quinn(Posted 2012) [#13]
rushibno said:

"I mean what wrong with :
Field data:T[][] = New T[width][height]"

What's wrong is that it doesn't work that way in Monkey, perhaps in part because it doesn't work that way in many of Monkey's target languages.

On the plus(?) side, you could make a triangular array in Monkey if you wanted - you are not confined to rectangles!

Just make a function like therevills said, and then you can initialise an array in one line in Monkey too.


golomp(Posted 2012) [#14]
@matty
it's exactly the simple but so efficient solution i also use.


Shinkiro1(Posted 2012) [#15]
Btw, muddy_shoes wrote a great article on array performance (specifically 1d vs 2d): http://pointlessdiversions.blogspot.co.nz/2012/05/1d-vs-2d-arrays-performance-reality.html


golomp(Posted 2012) [#16]
Thanks for this link Shinkiro1, it's a fine analyze.


Rushino(Posted 2012) [#17]
Thanks all for your replies.

Nice article Shinkiro. I see now why its better a 1d array. I was sure i could use a 2d array but well. I haven't taken care of the target. I will go the 1dim array route then. Its not much of a change anyway.. its just because i found the 2dim array more intuitive.

Also i was wondering would it be harder to add a third dimension to a 1dim array ?


golomp(Posted 2012) [#18]
More dimension you need less 1D adaptation is easy.
If you dont need particular performance you'll probably feel better
with 2D array using.
In another hand, if you make your own conversion formula
it's clear as crystal. (tab_in(x,y) , tab_out(x,y))


Rushino(Posted 2012) [#19]
I think its.. ( (row * height) + (col * width)) * 3 + depth


Shinkiro1(Posted 2012) [#20]
Arghh .. the point of the article is that it really doesn't matter from a performance standpoint if you use a 1D or 2D array (except for some cases).
Personally I prefer to use a 2D array, as for me it's much easier to read such code.
[monkeycode]
mapArray[3][4] = 10
[/monkeycode]


Rushino(Posted 2012) [#21]
Why are you angry ? :P


Gerry Quinn(Posted 2012) [#22]
I think there is a real performance difference in some predictable circumstances. I got a consistent speed boost by a factor of almost two when I implemented the Dijkstra algorithm using a 1D array instead of 2D. And the code was shorter, because a 1D array is indexed with ints instead of tuples, so when you are remembering a list of locations you have less to do.

However, a factor of two even in an important algorithm would probably not break any game. All in all, there is little reason not to use 2D if that's what you prefer.


golomp(Posted 2012) [#23]
I agree with you Gerry, even if 1D performance are better,
users must use what they prefer. If they use 2D and need performance
they still can modify source. Users must not be crystallized in a restrictive
dimension or criticised for their dimension critical choice.


Rushino(Posted 2012) [#24]
That why i think i should go the performance route but that only for my needs since im going to use pathfinding. Also i realised i needed a 3D array which make things worse.


golomp(Posted 2012) [#25]
Lets consider a 3D volume is a superposition of 2D arrays and you'll find a solution.
method:
In 1D for an element X1 you have direct access to tab_in[X1] and tab_out[X1]
in 2D for an element (X2,Y2) you have classic formula tab_in[f(X2,Y2)] and tab_out[f(X2,Y2)]
f(X2,Y2) return an element X1 wich give you 1D tab direct acces
in 3D for an element (X3,Y3,Z3) you have to found a formula considering a superposition
of 2D arrays lets call it g(X3,Y3,Z3) wich return you an
element(X2,Y2) usable with function f and finally obtain X1.
(You can use this step to verify your formula.)
After what by a composition of function f and g you will find the direct h function
wich transform (X3,Y3,Z3) directly to a single X1

I think h is a kind of function like :
f(X3,Y3)+Z3*step
with step=2D array size