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?

Asked By: utdiscant

||

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.

Answered By: Eevee

It’s clear you’re using numpy. With numpy you can just do:

for cell in self.cells.flat:
    do_somethin(cell)
Answered By: tom10

How about this:

import itertools
for cell in itertools.chain(*self.cells):
    cell.drawCell(surface, posx, posy)
Answered By: Tim Pietzcker

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
Answered By: Carl Bellingan

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.

Answered By: shahram kalantari

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

Answered By: Frank Bryce

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]))
Answered By: Alexey Tigarev