0
a = [1,2,3,4,0]
def looping_thing():
    append_flag = True
    for i in a:
        if i == 0:
            append_flag = False
        if append_flag:
            a.append(i)
        print(i)
looping_thing()

So in this code i am trying to move the item to back of the list so that i can deal with them only after i encounter value "0" in the list. So is this way of doing is correct in python?

Edit : So seems like i was not that clear. What i am doing here is....from the list i first want to deal with value 0 and execute some block of code..then move onto other value of the list and execute the same block of code. So i am just so to execute block of code "0" has the priority. Here the assumption is that i cannot sort the list and there will always be a "0" value. I hope this make sense.

4 Answers4

5

To answer your question, no, you should not modify a sequence you are iterating over. See more discussion here: Modifying list while iterating

If I understand you correctly, you want all items in the list until you encounter the first 0. Example: a = [1,2,3,4,0] -> [1,2,3,4]

If so, you can use the index method to find the index of the first 0 in your list, then take a slice to get all elements prior to that index.

def get_elems(list_in):
    if 0 not in list_in:
        return list_in
    i = list_in.index(0)
    return list_in[:i]
somebody3697
  • 206
  • 2
  • 4
  • so what i want is...first i want to process a block of code when i encounter 0 in the list...then after that i would execute block of code with the rest of the value. hope that makes sense..... assuming that the list will cannot be sorted...! – Mohit Sharma Feb 10 '22 at 05:18
  • How many times can 0 appear in the list? Do you need to keep lists of values between 0 separate? ie [1,2,3,0,4,5,6] -> [1,2,3], [4,5,6] or can they be stored in a single list? ie [1,2,3,0,4,5,6] -> [1,2,3,4,5,6] – somebody3697 Feb 10 '22 at 05:24
  • 0 can appear just once. and yeah they can be store in single list. – Mohit Sharma Feb 10 '22 at 05:30
  • I'm not clear on what you want to do with the results ("...first i want to process a block of code when i encounter 0 in the list...then after that i would execute block of code with the rest of the value"). If the values can be stored in a single list and you're not concerned with where the 0 is, then you can remove the 0 with a list comprehension, ie a = [1, 2, 3, 0, 4, 5, 6], b = [i for i in a if i != 0] – somebody3697 Feb 10 '22 at 05:38
0

In general I would avoid manipulating the list in place while you iterate over it, especially using an iterator i, where it's not explicit how that will behave stepping through elements that could shift, appear, and disappear.

Plus, if you have to program in other languages, iterating over a changing collection/list/array could behave differently. In Java, for example, java.util.ConcurrentModificationException is thrown.

Note also that in your particular case this will iterate and grow the list infinitely if there is no 0 in it.

Two alternatives:

Use external list

a = [1,2,3,4,5,0]

def looping_thing():
    append_flag = True
    changes = []
    
    for i in a:
        if i == 0:
            append_flag = False
        if append_flag:
            changes.append(i)
        print(i)

    # done iterating over a; apply changes
    a.extend(changes)

looping_thing()

Use explicit index (iterate over range)

a = [1,2,3,4,5,0]

def looping_thing():
    append_flag = True
    
    # i is index of original a without appended elements
    # n guaranteed not to be recalculated as a changes
    n = len(a)
    for i in range(n):
        if a[i] == 0:
            append_flag = False
        if append_flag:
            a.append(a[i])
        print(a[i])

looping_thing()
owengall
  • 455
  • 4
  • 11
0

It generally is not a good idea to append to the same list that you are iterating through without specifying an explicit range.

Unless you are absolutely certain that there will always be one "0" in your list, you will eventually run into an input that will cause an infinite loop. Take the following input for example.

[1, 2, 3]

Notice that there is no stopping condition because there are no elements equal to 0. This will cause you to keep appending 1, 2, 3 until you overflow.

One way to avoid iterating over new elements is to explicitly define your loop's range to be within the length of the original array.

for index in range(len(a)):
  print(a[index])
Van
  • 13
  • 5
0

Do not modify the thing you are iterating over. Bad things can and do happen. In your case you are lengthening the list (a.append(i)) as you iterate over it. Probably, the iteration will never reach the end of the loop and you have an infinite loop (but anything can happen). My understanding is that you want to move all items or the list before a possible 0 to the end of the list. Do this by finding the index or 0 in the list and then slicing.

    def move_to_back(lst):

        if 0 in lst:
           i=lst.index(0)
        else:
           return lst

        return  lst[i:] + lst(:i]
William
  • 324
  • 1
  • 8
  • Sorry that my question is not clear....but what i want to do mainly here is.... first i want to deal with value 0..then with the rest of the value on the list...! and here the assumption is there will alwys e 0 value and i cannot sort the list...! – Mohit Sharma Feb 10 '22 at 05:24