Francis Ouellette
Francis Ouellette

Reputation: 21

Converting a 1d array into 2d matrix in python

I am making a map editor where you can choose the size of X and Y.

In my example I will be using a 6x6 board. With Tkinter my values are stored in a dictionary and comes out in an array in this format:

{(0,"floor"), (1,"floor"), (2,"wall"), ..., (35,"wall")} 

What I want to do is to have the values in the format of a two dimensional array:

{([0,0],"floor"),([0,1],"floor"), ([0,2],"wall"), ..., ([5,5],wall)}

Here is draft code I am trying out, but doesn't seem to work like I want:

valueX = 6
valueY = 6 
totalSize = valueX * valueY 
matrix = []

for i in range(totalSize): 
    matrix.append([i/valueX,i%valueY])

This works for a 6x6 matrix, but when I try an irregular size like 6x10 it doesn't get the results I want.

Here is the result I want:

[0,0] [0,1]...[0,9],[0,10],[1,0]...

Here is what I get:

[[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [1, 6], [1, 7], [1, 8], [1, 9], [1, 0], [1, 1]]

Upvotes: 2

Views: 2717

Answers (3)

Nathaniel Ford
Nathaniel Ford

Reputation: 21249

First, lets clear some things up. A dictionary in Python without keys is known as a set. In the REPL:

>>> x = {1,2,3}
>>> x
{1, 2, 3}

>>> x = {1,2,3,1}
>>> x
{1, 2, 3}

We can see that a set will remove duplicate items. We have to be careful when we are talking about sets (which at their most general do not have an ordering and do not have duplicates) and when we are talking about lists (which have an order and can contain duplicates).

Secondly, a 'two dimensional array' implicitly indicates where an element exists in a two-dimensional plane (commonly referred to as a 'matrix'):

>>> y = [['a','b','c'],['d','e','f']]
>>> y[0][1]
'b'
>>>y[1][0]
'd'

This is subtly different from what you're constructing:

>>> z = [([0,0], 'a'), ([0,1], 'b'), ([0,2], 'c'), ([1,0], 'd'), ([1,1], 'e'), ([1,2], 'f')]
>>> z[1]
([0, 1], 'b')
>>> z[3]
([1, 0], 'd')

Therefore it is very important do define what you want your function to do. Either:

f(list of tuples) -> (list of tuples, with each tuple being tagged with it's coordinate)

Or:

f(list of tuples) -> (list of list of tuples, with each tuple having it's original index)

If the former:

new_list = list()
xDimension = 6
yDimension = 6  # Not actually used!
for (idx, element) in original_list:
    y = int(idx / valueX)  # rounds down
    x = idx % valueX
    new_list.append(([x,y], element))

Note that the above does not have the problem of the list being mismatched in length. Each tuple will be tagged with a coordinate, regardless of whether the original list 'fits' in the desired matrix size. Further, if it is too short, no errors arise. This is because we are simply iterating through the original list.

If the latter:

xDimension = 6
yDimension = 6
matrix = list()
for y in range(yDimension):
    row = list()
    for x in range(xDimension):
        idx = y*xDimension + x
        row.append(original_list[idx])
    matrix.append(row)

This does have the problem that the matrix might not contain all elements in the original list if it runs out of space. However, it will arrange the tuples in a multidimensional array of the desired size.

Upvotes: 0

armatita
armatita

Reputation: 13475

I agree with Matt Jordan. Just make sure you are ensuring an int output from those operations:

    matrix.append([int(i/valueY), i%valueY])

, Python 3 will give you problems if not (and even 2.x if you import division). Also you can always follow the more "intuitive" way of building such an iterable (although slower):

    matrix = []
    for x in range(valueX):
        for y in range(valueY):
            matrix.append([x,y])

You can change the order of the loops if you want to run lines of X first, and Y second.

Upvotes: 0

Matt Jordan
Matt Jordan

Reputation: 2181

Your computation for coordinates is incorrect - I believe this should work better:

matrix.append([i/valueY, i%valueY])

The first coordinate needs to be your X value, which will increment once for every "valueY" tuples in the list, so that is divided by valueY.

The second coordinate needs to be your Y value, which is in the range 0 to valueY-1, so i modulo valueY takes care of that.

I assume the code was a simplified example, since it doesn't attempt to handle the source data tuples at all.

Upvotes: 1

Related Questions