nickamcarthur - 4 months ago 12

Python Question

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...