Vectorize nested for loop Python
Question: I have a numpy array that I'm iterating through with:

    
    
    import numpy
    import math
    array = numpy.array([[1, 1, 2, 8, 2, 2],
                   [5, 5, 4, 1, 3, 2],
                   [5, 5, 4, 1, 3, 2],
                   [5, 5, 4, 1, 3, 2],
                   [9, 5, 8, 8, 2, 2],
                   [7, 3, 6, 6, 2, 2]])
    
    
    Pixels = ['U','D','R','L','UL','DL','UR','DR']
    
    for i in range (1,array.shape[0]-1):
        for j in range (1,array.shape[1]-1):
    
    
             list = []
             while len(list) < 2:
                    iToMakeList = i
                    jToMakeList = j
    
                    if iToMakeList > array.shape[0]-1 or iToMakeList < 1 or jToMakeList> array.shape[0]-1 or jToMakeList < 1:
    
                        break
    
                    PixelCoord = {
                'U' : (iToMakeList-1,jToMakeList),
                'D' : (iToMakeList+1,jToMakeList),
                'R' : (iToMakeList,jToMakeList+1),
                'L' : (iToMakeList,jToMakeList-1),
                'UL' : (iToMakeList-1,jToMakeList-1),
                'DL' : (iToMakeList+1,jToMakeList-1),
                'UR' : (iToMakeList-1,jToMakeList+1),
                'DR' : (iToMakeList+1,jToMakeList+1)
                    }
                    Value = {
                'U' : array[iToMakeList-1][jToMakeList],
                'D' : array[iToMakeList+1][jToMakeList],
                'R' : array[iToMakeList][jToMakeList+1],
                'L' : array[iToMakeList][jToMakeList-1],
                'UL' : array[iToMakeList-1][jToMakeList-1],
                'DL' : array[iToMakeList+1][jToMakeList-1],
                'UR' : array[iToMakeList-1][jToMakeList+1],
                'DR' : array[iToMakeList+1][jToMakeList+1]
                    }
    
    
                    candidates = []
                    for pixel in Pixels:
                        candidates.append((Value[pixel],pixel))
    
                    Lightest = max(candidates)
    
    
                    list.append(PixelCoord[Lightest[1]])
    
                    iToMakeList = PixelCoord[Lightest[1]][0]
                    jToMakeList = PixelCoord[Lightest[1]][1]
    

I want to accelerate this process. It's very slow.

Assume that the output of this snippet is my final goal and the ONLY thing I
want to do is accelerate this code.


Answer: For your question to make sense to me, I think you need to move where `list =
[]` appears. Otherwise you'll never get to even `i=0`, `j=1` until `list` is
full. I can't imagine that it is slow as currently implemented --- list will
be full very quickly, and then the for loops should be very fast. Here is what
I believe you intended. Please clarify if this is not correct.

    
    
    for i in range (0,array.shape[0]):
        for j in range (0,array.shape[1]):
             list = []
             while len(list) < 100:
                    print "identity", i, j
    
                    #find neighboring entry with greatest value (e.g., assume it is [i-1, j] with value 10)
                    list.append((i-1,j))
                    i = i-1
                    j = j
             #perform operations on list
    

Let's do some modifications. I'll assume there is a function
`get_max_nbr(i,j)` which returns the coordinates of the maximum neighbor. One
of the places your code is slow is that it will call get_max_nbr for the same
coordinate many times (at each step in the loop it does it 100 times). The
code below uses [memoization](http://stackoverflow.com/questions/1988804/what-
is-memoization-and-how-can-i-use-it-in-python) to get around this (down to 1
time on average). So if this is your bottleneck, this should get you close to
100 times speedup.

    
    
    maxnbr = {}
    for i in range(0,array.shape[0]):
        for j in range (0,array.shape[1]):
            list = []
            current_loc = (i,j)
            while len(list) < 100:
                if current_loc not in maxnbr:  #if this is our first time seeing current_loc
                    maxnbr[current_loc] = get_max_nbr(*current_loc) #note func(*(i,j)) becomes func(i,j)
                current_loc = maxnbr[current_loc]
                list.append(current_loc)
            #process list here                 
    

This doesn't successfully vectorize, but it does create the list (I think) you
want, and it should be a significant improvement. It may be that if we knew
more about the list processing we might be able to find a better approach, but
it's not clear.

