考虑以下示例:
In [1]: lst = list(range(10)) * 2
In [2]: lst
Out[2]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [3]: for i, x in enumerate(list(lst)):
...: if i > 10 and x % 2:
...: lst.remove(x)
...:
In [4]: lst
Out[4]: [0, 2, 4, 6, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
所以这个策略不起作用,因为它删除了 list 中第一次出现的项目,这不是我想要的。
In [5]: lst = list(range(10)) * 2
In [6]: for i, x in enumerate(list(lst)):
...: if i > 10 and x % 2:
...: del lst[i]
...:
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-6-bbec803a1844> in <module>()
1 for i, x in enumerate(list(lst)):
2 if i > 10 and x % 2:
----> 3 del lst[i]
4
IndexError: list assignment index out of range
我的其他策略也不起作用,因为初始 list 的副本最终具有更大的索引,因为原始 list 不断从中删除项目。
以下确实有效:
In [7]: lst = list(range(10)) * 2
In [8]: idx = 0
In [9]: for i, x in enumerate(list(lst)):
...: if i > 10 and x % 2:
...: lst.pop(i-idx)
...: idx += 1
...:
In [10]: lst
Out[10]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 2, 4, 6, 8]
还有这个:
In [11]: lst = list(range(10)) * 2
In [12]: idx = 0
In [13]: for i, li in enumerate(x for x in lst.copy()):
...: if i > 10 and li % 2:
...: lst.pop(i-idx)
...: idx += 1
...:
In [14]: lst
Out[14]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 2, 4, 6, 8]
有哪一种工作方法比另一种更好吗?有没有更好的方法来实现我想要的?如果我在 if 测试中有 or 语句怎么办?
In [15]: lst = list(range(10)) * 2
In [16]: idx = 0
In [17]: for i, x in enumerate(list(lst)):
...: if i > 10 and (x % 2 or x // 5):
...: lst.pop(i-idx)
...: idx += 1
...:
In [18]: lst
Out[18]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 2, 4]
请您参考如下方法:
每当您发现自己正在编写一个 for 循环来构造或修改一个列表时,请问问自己如何使用列表理解来完成它。列表理解是 Pythonic 的。
>>> [x for i, x in enumerate(lst) if i <= 10 or x % 2 == 0]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 2, 4, 6, 8]
