考虑以下示例:
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]
其中一种工作方法是否比其他方法更好?有没有更好的方法来实现我想要的?如果我在or
测试中有if
条语句怎么办?
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]
答案 0 :(得分:4)
每当您发现编写for
循环来构造或修改列表时,请问自己如何使用列表理解来实现。列表理解是Python的。
>>> [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]
答案 1 :(得分:1)
上面的解决方案将是我使用 list comprehension 的首选,但是对于另一种解决方案,即使只是为了学习新工具,我们也可以使用filterfalse
from itertools import filterfalse
l = [*range(10)]*2
l = list(filterfalse(lambda x: x[0] > 10 and x[1] % 2, enumerate(l)))
print([y for x, y in l])
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 2, 4, 6, 8]