39

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?

utdiscant
  • 11,128
  • 8
  • 31
  • 40

7 Answers7

51

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

for cell in self.cells.flat:
    do_somethin(cell)
tom10
  • 67,082
  • 10
  • 127
  • 137
  • 6
    I think now there is a more effective way of doing this with [`numpy.nditer()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.nditer.html) – tuned Mar 02 '17 at 10:27
32

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
Carl Bellingan
  • 1,460
  • 12
  • 7
19

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.

Eevee
  • 47,412
  • 11
  • 95
  • 127
  • 1
    You got it wrong. It should be: for cell in [cell for row in self.cells for cell in row]: do_something(cell) – xApple Sep 29 '11 at 11:18
  • Isn't the way he did it fine? It's just a generator expression instead of a list comprehension...am I missing something? O.o – Shon Freelen Oct 02 '11 at 11:20
8

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.

7

How about this:

import itertools
for cell in itertools.chain(*self.cells):
    cell.drawCell(surface, posx, posy)
Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
5

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

Frank Bryce
  • 8,076
  • 4
  • 38
  • 56
3

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]))
Alexey Tigarev
  • 1,915
  • 1
  • 24
  • 31