Iterating through a multidimensional array in Python
Question:
I have created a multidimensional array in Python like this:
self.cells = np.empty((r,c),dtype=np.object)
Now I want to iterate through all elements of my twodimensional array, and I do not care about the order. How do I achieve this?
Answers:
Just iterate over one dimension, then the other.
for row in self.cells:
for cell in row:
do_something(cell)
Of course, with only two dimensions, you can compress this down to a single loop using a list comprehension or generator expression, but that’s not very scalable or readable:
for cell in (cell for row in self.cells for cell in row):
do_something(cell)
If you need to scale this to multiple dimensions and really want a flat list, you can write a flatten
function.
It’s clear you’re using numpy. With numpy you can just do:
for cell in self.cells.flat:
do_somethin(cell)
How about this:
import itertools
for cell in itertools.chain(*self.cells):
cell.drawCell(surface, posx, posy)
If you need to change the values of the individual cells then ndenumerate (in numpy) is your friend. Even if you don’t it probably still is!
for index,value in ndenumerate( self.cells ):
do_something( value )
self.cells[index] = new_value
you can get the index of each element as well as the element itself using enumerate command:
for (i,row) in enumerate(cells):
for (j,value) in enumerate(row):
print i,j,value
i
,j
contain the row and column index of the element and value
is the element itself.
No one has an answer that will work form arbitrarily many dimensions without numpy, so I’ll put here a recursive solution that I’ve used
def iterThrough(lists):
if not hasattr(lists[0], '__iter__'):
for val in lists:
yield val
else:
for l in lists:
for val in iterThrough(l):
yield val
for val in iterThrough(
[[[111,112,113],[121,122,123],[131,132,133]],
[[211,212,213],[221,222,223],[231,232,233]],
[[311,312,313],[321,322,323],[331,332,333]]]):
print(val)
# 111
# 112
# 113
# 121
# ..
This doesn’t have very good error checking but it works for me
It may be also worth to mention itertools.product()
.
cells = [[x*y for y in range(5)] for x in range(10)]
for x,y in itertools.product(range(10), range(5)):
print("(%d, %d) %d" % (x,y,cells[x][y]))
It can create cartesian product of an arbitrary number of iterables:
cells = [[[x*y*z for z in range(3)] for y in range(5)] for x in range(10)]
for x,y,z in itertools.product(range(10), range(5), range(3)):
print("(%d, %d, %d) %d" % (x,y,z,cells[x][y][z]))
I have created a multidimensional array in Python like this:
self.cells = np.empty((r,c),dtype=np.object)
Now I want to iterate through all elements of my twodimensional array, and I do not care about the order. How do I achieve this?
Just iterate over one dimension, then the other.
for row in self.cells:
for cell in row:
do_something(cell)
Of course, with only two dimensions, you can compress this down to a single loop using a list comprehension or generator expression, but that’s not very scalable or readable:
for cell in (cell for row in self.cells for cell in row):
do_something(cell)
If you need to scale this to multiple dimensions and really want a flat list, you can write a flatten
function.
It’s clear you’re using numpy. With numpy you can just do:
for cell in self.cells.flat:
do_somethin(cell)
How about this:
import itertools
for cell in itertools.chain(*self.cells):
cell.drawCell(surface, posx, posy)
If you need to change the values of the individual cells then ndenumerate (in numpy) is your friend. Even if you don’t it probably still is!
for index,value in ndenumerate( self.cells ):
do_something( value )
self.cells[index] = new_value
you can get the index of each element as well as the element itself using enumerate command:
for (i,row) in enumerate(cells):
for (j,value) in enumerate(row):
print i,j,value
i
,j
contain the row and column index of the element and value
is the element itself.
No one has an answer that will work form arbitrarily many dimensions without numpy, so I’ll put here a recursive solution that I’ve used
def iterThrough(lists):
if not hasattr(lists[0], '__iter__'):
for val in lists:
yield val
else:
for l in lists:
for val in iterThrough(l):
yield val
for val in iterThrough(
[[[111,112,113],[121,122,123],[131,132,133]],
[[211,212,213],[221,222,223],[231,232,233]],
[[311,312,313],[321,322,323],[331,332,333]]]):
print(val)
# 111
# 112
# 113
# 121
# ..
This doesn’t have very good error checking but it works for me
It may be also worth to mention itertools.product()
.
cells = [[x*y for y in range(5)] for x in range(10)]
for x,y in itertools.product(range(10), range(5)):
print("(%d, %d) %d" % (x,y,cells[x][y]))
It can create cartesian product of an arbitrary number of iterables:
cells = [[[x*y*z for z in range(3)] for y in range(5)] for x in range(10)]
for x,y,z in itertools.product(range(10), range(5), range(3)):
print("(%d, %d, %d) %d" % (x,y,z,cells[x][y][z]))