multidimensional arrays in python

I know my problem is "wrong thinking" but here it is:

i want an array of integer values that i can reference with "x-y" coordinates:

so
        game:  1            2          3
team
1                 Win       Loss      Loss
2                 Loss     Win      Loss
3                 Loss    ....

i need the syntax for creating the array, assigning the values "win" and "loss" as appropriate, and then using those values... in my brain it should be:

results = [3][3]  # definition
results[0][0]="Win"
results[0][1]="Loss"
...
My thinking is wrong. Please help. Thanks (this example - teams and scores - bears no resemblance to my actual program).
Thanks!
LVL 10
AaronAbendAsked:
Who is Participating?
 
VenabiliCommented:
Your thinking is fine - it's python that is a bit strange with the multi-dimensions (they do not exist. so you need to cheat and make a list that has elements list.

My python is a bit rusty but something like

results= [' '] * n
for i in range(n):
     results[i] = [' '] * n

should get the array created ( the cycle being so that you do not end up creating all lines being references to each other). n is the size of your array. And of course you can fill it with anything besides ' ' :)
 
And then  you can use results[i][j] to get the proper element.
0
 
peprCommented:
Exactly as Venabili wrote.  The alternative also is to use the list comprehension.  Try the following:

Here the initial value is zero but it can be anything (None, 'init', whatever).  

The [ 0 ] * n means take the list with a single initial item and "multiply" it n times. The result is [0, 0, 0, 0, ... 0] with n items.

The list comprehension is [ f(n) for n in iterable ] with the meaning, create the list of f(n) where f is any function, the n is the temporary variable assigned by values from the iterable. The iterable is whatever can produce sequence of elements.

The range(n) produces the list of integers [0, 1, 2, ... n-1] (in Python 2) or iterator producing the same elements (in Python 3).

Putting it together, the list comprehension creates a list of elements where the element is the list of the initial values.
width = 3
height = 3

results = [ [ 0 ] * width for n in range(height) ]
print results

Open in new window

0
 
gelonidaCommented:
You can also implement (sparse) arrays as dicts.

your array would be a dict and the key would be a tuple with x and y coordinates.

Whether a list of lists or a dict withcoordinate  tuples as key is better really depends on your game and what you'd like to do with the data lateron.

result = {}
for x in range(3):
    for y in range(3):
        result[(x,y)] = 0  

0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
AaronAbendAuthor Commented:
gelonida used a dictionary, which i have used but is not really designed for this (it's more like a hash table than an array). Both Venabili and Pepr solutions worked, though Venabili required definition of n=0. I tried out both those options. Pepr's worked as written here because the variables were defined (complete). I added n=3 and Venabili's worked as well. Venabili was first and mostly correct, but Pepr was complete and informative (i now comprehend comprehension, which was not clear earlier). Points to both and thanks to all.
0
 
peprCommented:
There is one more way ;) -- without the list comprehension, utilizing the * operator once more
width = 3
height = 3

results = [ [ 0 ] * width ] * height     # here 0 could be whatever initial value

Open in new window

0
 
gelonidaCommented:
Pepr, the last solution is not working I'm afraid.
At least not with my cygwin python version.

a[0][0] and a[1][0] and a[2][0] would point all to the same element.
The list comprehension avoids this 'aliasing' problem.

 
Python 2.5.1 (r251:54863, May 18 2007, 16:56:43)
[GCC 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = [ [ 0 ] * 3 ] * 3
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][0] = 1
>>> a
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]


0
 
peprCommented:
Yes.  You are right.  The reason is that the * operators copies the existing items.  The list comprehension was used in a way when the new elements are created.  The difference is caused by immutable integer constant (here the initial zero) and the mutable nature of a list.  When the list is assigned, only the reference is copied.  The same holds also for integers.  However, if you try to modify the zero constant, it cannot be changed in situ.  On the other hand, the three smaller lists inside the one big list are identical.  They are created only by multiplication of the reference. In other words, there are only 3 integers stored in the [[1, 0, 0], [1, 0, 0], [1, 0, 0]].  It is only not visible directly.

It can be visualized via:  

print id(a[0])  # identification of the internal list object
print id(a[1])  # this should be the same
print id(a[2])  # and also this

I did not check it through Python -- just a guess.
0
 
VenabiliCommented:
AaronAbend,

Yeah - it was just a code snippet - sorry :)

For the last example:
That's why I did it with the cycle above - I remember something about python doing references instead of separate arrays when using * - thus the creation of the big list and then the creation of each one separately and my comment after this about the references:)

It drove me crazy the first thing I needed something like this in python - needed a lot of time to figure out what I am doing wrong.
0
 
VenabiliCommented:
~the first time I mean - should proofread before posting :)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.