Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to append to a list during iteration if I want to iterate over the added value?

Tags:

python

loops

I often find myself writing code like:

mylist = [247]
while mylist:
    nextlist = []
    for element in mylist:
        print element
        if element%2==0:
            nextlist.append(element/2)
        elif element !=1:
            nextlist.append(3*element+1)
    mylist = nextlist

Okay - it's generally not this simple [and usually it really is with long lists, I just chose this (see xkcd) for fun], but I create a list, iterate over it doing things with those elements. While doing this, I will discover new things that I will need to iterate over, and I put them into a new list which I then iterate over.

It appears to be possible to write:

mylist=[247]
for element in mylist:
    print element
    if element%2 == 0:
        mylist.append(element/2)
    elif element !=1:
        mylist.append(element*3+1)

I know that it's considered dangerous to modify a list while iterating over it, but in this case I want to iterate over the new elements.

Are there dangers from doing this? The only one I can think of is that the list may grow and take up a lot of memory (in many of my cases I actually want to have the whole list at the end). Are there others I'm ignoring?

Please note: Python: Adding element to list while iterating is related, but explains ways to create a copy of the list so that we can avoid iterating over the original. I'm asking about whether there is anything wrong in my specific case where I actually want my iteration to be extended.


edit: here is something closer to the real problem. Say we want to generate the "k-core" of a network. That is, delete all nodes with degree less than k. From remaining network delete all nodes with degree less than k. Repeat until none left to delete. The algorithm would find all less than k nodes to begin with, put them in a to_delete list. Then as nodes are deleted, if a neighbor's degree becomes k-1, add it to the list. This could be done by:

delete_list = [node for node in G.nodes() if G.degree(node)<k]
for node in delete_list:
    nbrs = G.neighbors(node)
    for nbr in nbrs:
        if G.degree(nbr)==k:
            delete_list.append(nbr)
    G.remove_node(node)
like image 401
Joel Avatar asked Aug 26 '15 07:08

Joel


1 Answers

Yes, it's fairly safe to append to a list you're iterating over, at least in the way that you're doing it. The only issue would be if the list grew so large that it caused memory issues, though that's only going to be an issue for you with very large numbers.

That said, I would probably use a while loop in this case, whether or not you want to have the entire list at the end.

current = 247
result_list = [current]

while current != 1:
    if current % 2 == 0:
        current /= 2
    else:
        current = current * 3 + 1

    result_list.append(current)

Though really I would probably use a generator.

def collatz(start):
    current = start

    yield current

    while current != 1:
        if current % 2 == 0:
            current /= 2
        else:
            current = current * 3 + 1

        yield current

Shout-out to the Collatz conjecture! :D

like image 161
Cyphase Avatar answered Oct 13 '22 11:10

Cyphase