我有一个字符串列表。我有一个函数,给定一个字符串返回0或1.如何删除列表中函数返回0的所有字符串?
答案 0 :(得分:7)
[x for x in lst if fn(x) != 0]
这是一个“列表理解”,是Python中最好的语法糖之一,通常在其他语言中使用代码行和其他变量声明等。
请参阅: http://docs.python.org/tutorial/datastructures.html#list-comprehensions
答案 1 :(得分:3)
我会在列表推导上使用生成器表达式来避免可能很大的中间列表。
result = (x for x in l if f(x))
# print it, or something
print list(result)
与列表理解类似,这不会修改原始列表。
答案 2 :(得分:1)
修改:请在底部找到最佳答案。
如果您需要改变现有列表,例如因为您在其他地方有另一个引用,则需要实际remove
列表中的值。
我不知道Python中有任何这样的函数,但是这样的东西可以工作(未经测试的代码):
def cull_list(lst, pred):
"""Removes all values from ``lst`` which for which ``pred(v)`` is false."""
def remove_all(v):
"""Remove all instances of ``v`` from ``lst``"""
try:
while True:
lst.remove(v)
except ValueError:
pass
values = set(lst)
for v in values:
if not pred(v):
remove_all(v)
一个可能更有效的替代品,可能看起来有点太像C代码,对某些人的口味:
def efficient_cull_list(lst, pred):
end = len(lst)
i = 0
while i < end:
if not pred(lst[i]):
del lst[i]
end -= 1
else:
i += 1
编辑... :正如Aaron在评论中指出的那样,可以通过类似
的方式更加干净地完成def reversed_cull_list(lst, pred):
for i in range(len(lst) - 1, -1, -1):
if not pred(lst[i]):
del lst[i]
<强> ...修改
使用这些例程的技巧是使用像(一个)其他响应者所建议的enumerate
之类的函数,不会考虑列表元素已被删除的事实。我知道的唯一方法是手动跟踪索引而不是允许python进行迭代。那里肯定会有速度折衷,所以最好只做一些像
lst[:] = (v for v in lst if pred(v))
实际上,现在我想到了,这是迄今为止在列表上进行“就地”过滤的最明智的方法。在用它们填充lst
的元素之前迭代生成器的值,因此没有索引冲突问题。如果你想让这个更明确,那就去做
lst[:] = [v for v in lst if pred(v)]
在效率方面,我不认为这种情况会有太大影响。
如果我正确理解它们的实际工作原理,最后两种方法中的任何一种都会制作一份额外的列表副本,因此,如果你正在处理某些问题,上面提到的一个真正的就地解决方案会更好“巨大的土地。”
答案 3 :(得分:0)
>>> s = [1, 2, 3, 4, 5, 6]
>>> def f(x):
... if x<=2: return 0
... else: return 1
>>> for n,x in enumerate(s):
... if f(x) == 0: s[n]=None
>>> s=filter(None,s)
>>> s
[3, 4, 5, 6]
答案 4 :(得分:0)
使用生成器表达式:
alist[:] = (item for item in alist if afunction(item))
功能:
alist[:] = filter(afunction, alist)
或:
import itertools
alist[:] = itertools.ifilter(afunction, alist)
所有等价物。
您还可以使用列表理解:
alist = [item for item in alist if afunction(item)]
就地修改:
import collections
indexes_to_delete= collections.deque(
idx
for idx, item in enumerate(alist)
if afunction(item))
while indexes_to_delete:
del alist[indexes_to_delete.pop()]