用于迭代更改列表的Python习惯用法

时间:2014-09-26 18:27:51

标签: python for-loop

在python中是否有更好(更明显/惯用)的方法来编写等效的

index = 0
while index < len(some_list):
    do_some_stuff(some_list[index]) # may have many side effects
    if delete_element(some_list[index]):
        del some_list[index]
    else:
        index += 1

或字典相当于词典的字典?字典/列表理解不是一个问题,因为delete_element的结果可能取决于do_some_stuff

4 个答案:

答案 0 :(得分:3)

您可以将操作分解为两个单独的循环,并对第二部分使用列表推导。

for value in some_list:
    do_some_stuff(value)

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

另一个解决方案是迭代列表的副本,并使用enumerate来跟踪索引,而无需手动维护计数器。

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

您希望向后迭代,因此您无需为已删除的元素调整index

答案 1 :(得分:1)

如果顺序无关紧要,您可以向后枚举,以便删除不会弄乱您尚未处理的列表部分。

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

如果订单确实重要,请反转列表,执行此操作然后再将其反转。这会让他们感到困惑!

根据具体情况,您可以使用无标记替换项目。要么将其剥离出来,要么将此列表用于其他地方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]

答案 2 :(得分:0)

您甚至可以假设do_some_stuff返回item,执行以下操作:

res = [item for item in some_list if not delete_element(do_some_stuff(item))]

答案 3 :(得分:0)

严肃的方法是使用生成器:

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

然后得到一个可迭代的:

items = do_stuff_and_filter_items(items)

或获取清单:

items = list(do_stuff_and_filter_items(items))

或覆盖旧列表:

items[:] = do_stuff_and_filter_items(items)