我有一个字符串列表。我有一个函数,给定一个字符串返回0或1。如何删除所有函数返回0的字符串?
[x for x in lst if fn(x) != 0]
result = (x for x in l if f(x))
# print it, or something
print list(result)
就像列表推导式一样,这个操作不会直接修改你的原始列表。
编辑: 最佳答案请见底部。
如果您需要更改现有列表,例如因为您在其他位置有对它的引用,那么您将需要实际删除
列表中的值。
我不知道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)]
我认为在这种情况下,从效率上讲不会有太大的区别。
如果我正确理解它们的工作原理,这两种方法中的任何一种都将使列表多出一个副本,因此,如果你正在处理一些“巨大的土地”,那么上面提到的任何一种真正的原地解决方案都会更好。
end
的值。同时,while
中也没有分支。 - aaronasterlingreversed
。生成器解决方案可能是最好的,但它不会就地修改列表。 - D.Shawley用生成器表达式:
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()]
>>> 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]
[1, 2, 3, 4, 5, 6]
和 f = lambda v: v <= 2
,我得到了 [1, 2, 4, 6]
。 - intuited
fn(x)
" 更符合惯用语,并且适用于 Python 认为真/假的任何值(您的函数返回0或1,但没有理由硬编码这种假设)。 - Beni Cherniavsky-Paskin