用于在不断变化的列表上进行迭代的Python习惯用法
python中有没有更好(更明显/更惯用)的方法来编写用于在不断变化的列表上进行迭代的Python习惯用法,python,for-loop,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 index=0 而索引
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
index=0
而索引
或者是字典里的字典?Dict/list理解不是一件事,因为
delete\u element
的结果可能取决于do\u some\u stuff
您可以将操作分解为两个单独的循环,并对第二部分使用list理解
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]
您希望向后迭代,这样就不必为删除的元素调整
索引。如果顺序不重要,您可以向后枚举,这样删除操作就不会弄乱列表中尚未处理的部分
for i, item in enumerate(reversed(somelist), -len(somelist)+1):
do_some_stuff(item)
if delete_element(item):
del somelist[-i]
如果顺序确实重要,则颠倒列表,执行此技巧,然后再次颠倒。那会把他们弄糊涂的
根据情况,您可以使用类似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]
你甚至可以假设做一些东西
返回项
,这样做:
res = [item for item in some_list if not delete_element(do_some_stuff(item))]
毫无意义的方法是使用发电机:
def do_stuff_and_filter_items(items):
for item in items:
do_some_stuff(item)
if not delete_element(item):
yield item
然后,要获得一个iterable:
items = do_stuff_and_filter_items(items)
或获取列表:
items = list(do_stuff_and_filter_items(items))
或覆盖旧列表:
items[:] = do_stuff_and_filter_items(items)
enumerate
从零开始向上计数,即使在反向迭代器上调用它也是如此。您需要使用del some\u list[-index-1]
以便删除的索引与项目一起倒计时。您的enumerate
调用不会生成与反向值匹配的索引(somelist[-len(somelist)+1]
是somelist[0]
)。您可能需要枚举(反向(somelist),1)
然后是del somelist[-index]
@Blckknght-您的权利,我想使用abs(I)。enumerate不倒计时,所以技巧是从负数开始,然后让它变为零。但是,正如您所说,使用负索引删除错误的值。-代码中已修复。啊,这确实更好。但是,我会使用-I
而不是abs(I)
,因为后者会检查该值的符号,而您不需要它(您总是希望对现有值求反)。@Blckknght-也改变了这一点。每个循环剪切一个甜美的.00000003秒(微笑)。考虑到我未说明的修改列表的要求,这个答案最适合。它还教会了我传递第二个参数进行枚举的好技巧。