在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
。
答案 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)