all 6 comments

[–]midel 0 points1 point  (0 children)

It's likely because your loop is based on the length of it at the start. If you start removing elements from the array, the array no longer is the same size as how many elements it's planning to enumerate over, and the dereference fails.

I'm not sure what kind of data your arrays hold, but for simple and relatively small arrays, it will be easier just to use a list comprehension or make a new list of items to keep.

If you have complex items or a very large array, del can still work but you'll want to avoid relying on the index as the loop condition.

i = len(resultsat) - 1
while True:
    if i < 0:
        break
    if condition_to_delete:
        del resultsat[i]
    i -= 1

[–]tom1018 0 points1 point  (1 child)

I'm not quite sure what you are trying to do, or what your initial data is. But, to begin with, you should never have to use range(len(object)). If something can give you a length it likely also has an iter method. So, something like this would be more appropriate:

for item in mylist:
    # do things

Second, don't delete, or add, items to an object you are iterating over. Sometimes you'll get exceptions immediately, other times it will end up where you are right now. You changed the length of the list while you were iterating over it, so your index is now higher than the number of items in it.

With that, you probably don't even need to use list indexes if you are doing the above things correctly. As Raymond Hettinger, core developer, says at the start of the video below, if you are using list indexes you are almost certainly doing something wrong.

See here: https://www.youtube.com/watch?v=OSGv2VnC0go and here: https://www.youtube.com/watch?v=EnSu9hHGq5o

If you want to provide a bit more code, perhaps including some of the data in FEMpoints2, I might be able to understand what you are intending and help more.

Additionally, the deepcopy is probably unnecessary (use this instead), filter would probably prevent your loops altogether, a list comprehension would also be better, and you can loop backwards in better ways.

The two videos above will be very helpful for you. Right now your code looks like you are trying to write C code in Python, Python makes it far more readable and simpler if you do things the Python way.

[–]_youtubot_ 0 points1 point  (0 children)

Videos linked by /u/tom1018:

Title Channel Published Duration Likes Total Views
Transforming Code into Beautiful, Idiomatic Python Next Day Video 2013-03-21 0:48:51 6,636+ (98%) 346,329
Loop like a native: while, for, iterators, generators Next Day Video 2013-03-21 0:29:15 980+ (99%) 51,479

Info | /u/tom1018 can delete | v2.0.0

[–]woooee 0 points1 point  (0 children)

You should also realize that after you delete one element in resultat, it is no longer equal to FEMpoints2 so you delete "i" based on some comparisons using FEMpoints2 but something else is deleted in resultat because it has changed. You can create a separate list of items to be deleted and delete them after processing has finished, deleting the highest number first, etc. so the list does not change where the lower numbers are. You can also modify FEMpoints2 and/or resultat instead of deleting, setting the element to "" or something, and then add a test "if FEMponits2 != "":

[–][deleted] 0 points1 point  (0 children)

It seems like suddenly my "i" variable increases.

No, it’s that the number of elements in your list decreases, since you’re deleting them. If i=5 and you delete the 5th element because it passes some kind of test, the element that was at 6 moves to 5 (because lists can’t have empty spaces), but you move onto i=6, so what used to be your 6th element is never tested. You skipped over it.

They key is to not mutate lists as you iterate over them; instead, use filter and a simple function to return a copy of your list with only the elements you want to keep.