nickamcarthur nickamcarthur - 1 month ago 4
Python Question

Converting 3 dimension array into 1 dimensional list in python

I am trying to take characters from a file and store them in a 3 dimensional array but to do this I need to convert the 3 dimensional array index into a single index.

I looked up how to do this and for this

def convert(file, w, h):
pix = [[["", "", ""] for x in range(w)] for y in range(h)]
for x in range(w):
for y in range(h):
for c in range(3):
pix[x][y][c] = ord(file[(x * w * h) + (y * h) + c])
return pix


However

file[(x * w * h) + (y * h) + c]


Is not giving me the correct values.

w and h change depending on the text file, but the third dimension is always 3 deep.

How can I do this?

Answer

I believe the following is correct:

def convert(file, w, h):
    pix = [[["", "", ""] for y in range(h)] for x in range(w)]
    for x in range(w):
        for y in range(h):
            for c in range(3):
                pix[x][y][c] = ord(file[(x * h * 3) + (y * 3) + c])
    return pix

First, I changed the order of the comprehension loops in pix to match the loop below. Next, I changed the indexing of file. Note that when x and y are both 0, you'll pick up elements 0, 1 and 2 because that is the range of c. The next element that you want to pick up is 3 (when x = 0, y = 1, c = 0). The only way for that to happen is if you multiply y by 3. We can then apply the same logic to see that we need to multiply x by h and 3 (since those are the sizes of the "faster" running dimensions).

Note that for things like this, numpy is really nice:

import numpy as np
print(np.reshape(range(36), (3, 4, 3)))

Of course, this doesn't convert the characters to integers based on their ordinal -- but that's easy enough to do in pre-processing:

pix = np.reshape([ord(c) for c in file], (3, 4, 3))

As a bonus, then you get to work with pix as a numpy array instead of as a list of list of list...

Comments