为啥 Python for 循环在遍历列表副本并进行删除时会跳过元素? [复制]

Posted

技术标签:

【中文标题】为啥 Python for 循环在遍历列表副本并进行删除时会跳过元素? [复制]【英文标题】:Why does Python for-loop skip elements when iterating over a copy of a list and making deletions? [duplicate]为什么 Python for 循环在遍历列表副本并进行删除时会跳过元素? [复制] 【发布时间】:2019-03-21 13:55:34 【问题描述】:

我正在遍历一个列表,有时我会从另一个列表中删除一个元素。 for 循环不会从另一个列表中删除元素,而是跳过整个实际迭代。我找到了解决方案,但我不太了解。

这是一个代码示例。除了我注释掉final_dt_list.remove(dt)这一行之外,它是相同的两倍:

dt_list = [3600, 2700, 1800, 900]
final_dt_list = dt_list
for dt in dt_list:
    print(dt)
    if not((3600/dt).is_integer()):
        print('skipped '+str(dt))
        final_dt_list.remove(dt)
        continue
    print('ok')

print('\n \n')

dt_list = [3600, 2700, 1800, 900]
final_dt_list = dt_list
for dt in dt_list:
    print(dt)
    if not((3600/dt).is_integer()):
        print('skipped '+str(dt))
        #final_dt_list.remove(dt)
        continue
    print('ok')

我得到的结果是:

3600
ok
2700
skipped 2700
900
ok



3600
ok
2700
skipped 2700
1800
ok
900
ok

正如您在第一个循环的结果中看到的那样,1800 没有打印出来,只是没有任何反应。

最后对我有用的是创建一个我想要删除的项目列表。而不是创建一个新的循环来遍历我想要删除的项目。然后,这个新循环将从 final_dt_list 中删除每个元素。

在此处查看解决方案代码:

for r in removed:
    final_dt_list.remove(r)

为什么现在有效,而不是上面的示例?我很困惑。

提前致谢!

【问题讨论】:

final_dt_list = dt_list 您只是在引用原始列表。对dt_list 的任何更改都将反映在final_dt_list 中,反之亦然。您可以使用final_dt_list = dt_list.copy()。如需更多信息,请阅读this 和this。第二个链接解释了如何复制列表 @Bazingaa 谢谢,我不知道。感觉我应该有。 这是别名。具体来说,您正在迭代列表的别名并进行删除。所以删除发生在原始和别名上。 无论如何,列表推导 是一种更清晰、更短、更简单的代码习惯用法,可以选择性地从满足条件的列表中挑选项目。你不需要for循环。在 Python 中,对于在其他语言(例如 Java)中需要列表的许多事情,您不需要 for 循环。请阅读此内容。 final_dt_list = [d for d in dt_list if (3600 % d)==0]。这是一个单线! 【参考方案1】:

dt_listfinal_dt_list 指向同一个对象(aliasing)。 您在循环时编辑列表。由于您只保留用于循环的指针,因此您会记住位置,但由于元素消失,它们会发生变化。

尝试通过以下方式记住要删除的元素:

    dt_list = [3600, 2700, 1800, 900]
    rm_list = []
    for dt in dt_list:
        print(dt)
        if not((3600/dt).is_integer()):
            print('skipped '+str(dt))
            rm_list.append(dt)
            continue
        print('ok')
    dt_list = [x for x in dt_list if x not in rm_list]

编辑:

从一开始就使用列表理解导致:

dt_list = [3600, 2700, 1800, 900]
dt_list = [x for x in dt_list if (3600/x).is_integer()]

【讨论】:

以上是关于为啥 Python for 循环在遍历列表副本并进行删除时会跳过元素? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥带有pop-method(或del语句)的for循环不会遍历所有列表元素

Python:为啥这个 for 循环在第一次迭代后退出?

python中为啥我的for循环里嵌套的if只能循环一次?

为啥 for 循环不遍历列表中的每个项目?

使用for循环遍历python中的列表

Python:使用 while 或 for 循环遍历列表