Python idiom for iterating over changing list

前端 未结 4 1505
死守一世寂寞
死守一世寂寞 2021-01-21 09:41

Is there a better (more obvious/idiomatic) way in python to write an equivalent of

index = 0
while index < len(some_list):
    do_some_stuff(some_list[index])         


        
相关标签:
4条回答
  • 2021-01-21 10:13

    If order doesn't matter, you can enumerate backwards so that deletes don't mess up the part of the list you haven't processed yet.

    for i, item in enumerate(reversed(somelist), -len(somelist)+1):
        do_some_stuff(item)
        if delete_element(item):
            del somelist[-i]
    

    If order does matter, reverse the list, do this trick then reverse it again. That'll confuse 'em!

    Depending on the situation, you could replace the item with a marker like None. Either strip it out later or have other places this list is used chack None.

    for i, item in enumerate(somelist)):
        do_some_stuff(item)
        if delete_element(item):
            somelist[i] = None
    
    somelist = [item for item in somelist if item]
    
    0 讨论(0)
  • 2021-01-21 10:29

    you could even, assuming that do_some_stuff returns item, do something like:

    res = [item for item in some_list if not delete_element(do_some_stuff(item))]
    
    0 讨论(0)
  • 2021-01-21 10:35

    You might break up the operations into two separate loops, and use a list comprehension for the second part.

    for value in some_list:
        do_some_stuff(value)
    
    some_list = [value for value in some_list if not delete_element(value)]
    

    Another solution would be to iterate over a copy of the list, and use enumerate to keep track of the indices without having to maintain a counter by hand.

    for index, value in enumerate(some_list[::-1]):
        do_some_stuff(value)
        if delete_element(value):
            del some_list[-index - 1]
    

    You'd want to iterate backwards so you don't have to adjust index for the deleted elements.

    0 讨论(0)
  • 2021-01-21 10:36

    The no-nonsense way is to use a generator:

    def do_stuff_and_filter_items(items):
        for item in items:
            do_some_stuff(item)
            if not delete_element(item):
                yield item
    

    Then to get an iterable:

    items = do_stuff_and_filter_items(items)
    

    or to get a list:

    items = list(do_stuff_and_filter_items(items))
    

    or to overwrite the old list:

    items[:] = do_stuff_and_filter_items(items)
    
    0 讨论(0)
提交回复
热议问题