什么是从列表中删除不满足约束的所有元素的快速方法?

时间:2010-10-09 02:15:14

标签: python

我有一个字符串列表。我有一个函数,给定一个字符串返回0或1.如何删除列表中函数返回0的所有字符串?

5 个答案:

答案 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()]