1

I am trying to do a simple filtering on python arrays. I have 2 arrays: a_array that has full set of values of some sort of Id, and lookup array that has subset of a_array. I want to keep only id that are present in my lookup array, I am trying with pop method to remove the values from a_array which are not present in lookup array but it ends up with Index out of range, I understand every time a value is removed from a_array its size gets changed hence we get index of range exception , how do I fix this problem.

a_array=[1,2,3,4,5,6,7,14,8,9,100,19,200,300,45,67,989,45,201]
loopkup = [2, 14,100,200,300]

def demo_func(a_array, loopkup):
    for i in range(len(a_array)):
        if a_array[i] not in loopkup:
            print('poping customer id {0}-->{1}' + str(i))
            a_array.pop(i)


def main():
    demo_func(a_array, loopkup)

if __name__ == '__main__':
    main()

Exception:

poping customer id {0}-->{1}0
poping customer id {0}-->{1}1
poping customer id {0}-->{1}2
poping customer id {0}-->{1}3
poping customer id {0}-->{1}4
poping customer id {0}-->{1}6
poping customer id {0}-->{1}8
poping customer id {0}-->{1}9
poping customer id {0}-->{1}10
Traceback (most recent call last):
  File "<string>", line 15, in <module>
  File "<string>", line 12, in main
  File "<string>", line 6, in demo_func
IndexError: list index out of range
nilesh1212
  • 1,561
  • 2
  • 26
  • 60

5 Answers5

4

Removing elements from a list within a for-loop, is considered as bad practise.


You can use a simple list comprehension in order to keep only the elements of array_a that also appear in loopkup:

def demo_func(a_array, loopkup):
    return [e for e in a_array if e in lookup]

Alternatively, you can also filter() your list:

def demo_func(a_array, loopkup):
    return list(filter(lambda e: e in a_array, loopkup))
Giorgos Myrianthous
  • 36,235
  • 20
  • 134
  • 156
2

The problem is that the maximum value of the range you're looping isn't being updated with each pop. You can do something similar to what you're doing with a while loop. Here, I update the array size, n, after each pop.

def demo_func(a_array, loopkup):
    i = 0
    n = len(a_array)
    while (i < n):
        if a_array[i] not in loopkup:
            print('poping customer id {0}-->{1}' + str(i))
            a_array.pop(i)
            n -= 1
        else:
            i += 1
JoaoCostaIFG
  • 161
  • 5
1

The simplest fix is looping over the array backwards:

def demo_func(a_array, loopkup):
    for i in reversed(range(len(a_array))):
        if a_array[i] not in loopkup:
            print('poping customer id {0}-->{1}' + str(i))
            a_array.pop(i)
joostblack
  • 2,465
  • 5
  • 14
1

The error is occurring because you are iterating over a sequence of numbers - the original size of the list. Once the list shrinks, the index no longer exists.

You should use list comprehension as:

a_array=[1,2,3,4,5,6,7,14,8,9,100,19,200,300,45,67,989,45,201]
lookup = [2, 14,100,200,300]
a_array = [elt for elt in a_array if elt not in lookup]
print(a_array)

Or iterate over elements directly instead of indexes as:

for elt in lst:
    # do something

Note: It is considered a bad practice to manipulate containers while iterating over them due to the failures you see above.

Krishna Chaurasia
  • 8,924
  • 6
  • 22
  • 35
0

A simple method to do the task is to modify the a_array.

a_array=[1,2,3,4,5,6,7,14,8,9,100,19,200,300,45,67,989,45,201]
loopkup = [2, 14,100,200,300]
a_array = [i for i in a_array if i in loopkup]

The 3rd line of the above code actually creates an array with id's that are present in a_array which are also present in lookup array.

Lavanya V
  • 337
  • 2
  • 7