S P
S P

Reputation: 1811

Python: Efficiently iterating over a multidimensional list

I'm using for-loops to iterate over two-dimensional list:

def itr(lpic, lH, lW, x, y):
    '''lpic=2D-Array; lH=Row_count; lW=Column_count;'''
    stack = []
    range_x = range(x-1, x+2)
    range_y = range(y-1, y+2)
    append = stack.append
    for i in range_x:
                if 0<=i<lH:#i is a valid index *Updated
                    for j in range_y:
                        if (0<=j<lW) and (lpic[i][j]=="0"):
                            lpic[i][j] = "1"
                            append([i, j])
    return stack

I'd like to know if there is a better way to do the same with Python2.5.

Upvotes: 3

Views: 3220

Answers (2)

werewindle
werewindle

Reputation: 3029

There are two simple optimizations for your code:

  1. Use xrange instead for range. This will prevent from generation two temporary lists.

  2. Use min and max in parameters for xrange to omit 'if' in outer loop. So you code will look like that:

def itr(lpic, lH, lW, x, y):
    '''lpic=2D-Array; lH=Row_count; lW=Column_count;'''
    stack = []
    range_x = xrange(max(0,x-1), min(lH,x+2))
    range_y = xrange(max(0,y-1), min(lW,y+2))
    append = stack.append
    for i in range_x:
      for j in range_y:
          if lpic[i][j]=="0":
              lpic[i][j] = "1"
              append([i, j])
    return stack

This will slightly increase performance.

Upvotes: 5

Amber
Amber

Reputation: 526613

Not really. In Python 2.6 if you wanted to compact your code a little, you could use itertools.product() to turn it into a single for loop, but the general efficiency wouldn't change at all - you'd still have N*M iterations of the loop.

import itertools

def itr(lpic, lH, lW, x, y):
    '''lpic=2D-Array; lH=Row_count; lW=Column_count;'''
    stack = []
    range_x = range(x-1, x+2)
    range_y = range(y-1, y+2)
    append = stack.append
    for i,j in itertools.product(range_x, range_y):
        if 0 <= i < lh and 0 <= j < lW and lpic[i][j]=="0":
            lpic[i][j] = "1"
            append([i, j])
    return stack

Upvotes: 5

Related Questions