基于谓词从列表中删除元素

时间:2009-12-08 11:21:08

标签: python string

我想从列表中删除元素,以便元素包含'X''N'。我必须申请大型基因组。这是一个例子:

输入:

codon=['AAT','XAC','ANT','TTA']

预期产出:

codon=['AAT','TTA']  

9 个答案:

答案 0 :(得分:6)

出于基础目的

>>> [x for x in ['AAT','XAC','ANT','TTA'] if "X" not in x and "N" not in x]
['AAT', 'TTA']

但如果您有大量数据,我建议您使用dict或设置

如果你有许多不同于X和N的字符,你可以这样做

>>> [x for x in ['AAT','XAC','ANT','TTA'] if not any(ch for ch in list(x) if ch in ["X","N","Y","Z","K","J"])]
['AAT', 'TTA']

注意:list(x)可以只是x,而["X","N","Y","Z","K","J"]可以只是"XNYZKJ",并且可以参考gnibbler回答,他做得最好。

答案 1 :(得分:4)

另一种不是最快的方式,但我觉得它很好看

>>> [x for x in ['AAT','XAC','ANT','TTA'] if not any(y in x for y in "XN")]
['AAT', 'TTA']

>>> [x for x in ['AAT','XAC','ANT','TTA'] if not set("XN")&set(x)]
['AAT', 'TTA']

对于长密码子,这种方式会更快(假设有一些重复)

codon = ['AAT','XAC','ANT','TTA']
def pred(s,memo={}):
    if s not in memo:
        memo[s]=not any(y in s for y in "XN")
    return memo[s]

print filter(pred,codon)

这是詹姆斯布鲁克斯建议的方法,你必须测试看哪个数据更快

codon = ['AAT','XAC','ANT','TTA']
def pred(s,memo={}):
    if s not in memo:
        memo[s]= not set("XN")&set(s)
    return memo[s]

print filter(pred,codon)

对于此样本密码子,使用集合的版本大约慢10%

答案 2 :(得分:2)

还有使用过滤器

的方法
    lst = filter(lambda x: 'X' not in x and 'N' not in x, list)

答案 3 :(得分:2)

  1. filter(lambda x: 'N' not in x or 'X' not in x, your_list)
  2. your_list = [x for x in your_list if 'N' not in x or 'X' not in x]

答案 4 :(得分:2)

是否有重复整个列表的原因?怎么样:

>>> def pred(item, haystack="XN"):
...     return any(needle in item for needle in haystack)
...
>>> lst = ['AAT', 'XAC', 'ANT', 'TTA']
>>> idx = 0
>>> while idx < len(lst):
...     if pred(lst[idx]):
...         del lst[idx]
...     else:
...         idx = idx + 1
...
>>> lst
['AAT', 'TTA']

我知道列表理解现在是所有的愤怒,但如果列表很长,我们不想在没有任何理由的情况下复制它吗?您可以将其用于下一步并创建一个很好的实用程序函数:

>>> def remove_if(coll, predicate):
...     idx = len(coll) - 1
...     while idx >= 0:
...         if predicate(coll[idx]):
...             del coll[idx]
...         idx = idx - 1
...     return coll
...
>>> lst = ['AAT', 'XAC', 'ANT', 'TTA']
>>> remove_if(lst, pred)
['AAT', 'TTA']
>>> lst
['AAT', 'TTA']

答案 5 :(得分:1)

我非常喜欢gnibbler的记忆方法。使用memoization的任何一种方法在大数据集的大图中都应该相同,因为备忘录字典应该快速填充并且应该很少执行实际测试。考虑到这一点,我们应该能够为大型数据集提高性能。 (这对于非常小的人来说需要付出一些代价,但是谁关心这些?)以下代码只需要在备忘录中找到一个项目,而不是两次(一次确定成员资格,另一次提取价值)。

codon = ['AAT', 'XAC', 'ANT', 'TTA']
def pred(s,memo={}):
    try:
        return memo[s]
    except KeyError:
        memo[s] = not any(y in s for y in "XN")
    return memo[s]

filtered = filter(pred, codon)

正如我所说,当基因组很大(或至少不是非常小)时,这应该明显加快。

如果您不想复制列表,只是遍历已过滤的列表,请执行以下操作:

for item in (item for item in codon if pred):
    do_something(item)

答案 6 :(得分:1)

如果您正在处理非常大的列表,那么您希望使用不涉及遍历整个列表的方法,而不是您绝对需要的方法。

您最好的选择可能是创建过滤功能,并使用itertools.ifilter,例如:

new_seq = itertools.ifilter(lambda x: 'X' in x or 'N' in x, seq)

这推迟实际测试列表中的每个元素,直到您实际迭代它。请注意,您可以像过滤原始序列一样过滤过滤后的序列:

new_seq1 = itertools.ifilter(some_other_predicate, new_seq)

修改

另外,稍微测试表明,在一个集合中记忆发现的条目可能提供足够的改进值得做,并且使用正则表达式可能不是要走的路:

seq = ['AAT','XAC','ANT','TTA']
>>> p = re.compile('[X|N]')
>>> timeit.timeit('[x for x in seq if not p.search(x)]', 'from __main__ import p, seq')
3.4722548536196314
>>> timeit.timeit('[x for x in seq if "X" not in x and "N" not in x]', 'from __main__ import seq')
1.0560532134670666
>>> s = set(('XAC', 'ANT'))
>>> timeit.timeit('[x for x in seq if x not in s]', 'from __main__ import s, seq')
0.87923730529996647

答案 7 :(得分:0)

正如S.Mark所要求的那样是我的版本。它可能更慢,但确实可以更容易地改变被删除的内容。

def filter_genome(genome, killlist = set("X N".split()):
    return [codon for codon in genome if 0 == len(set(codon) | killlist)]

答案 8 :(得分:0)

使用正则表达式比在某个字符的相同字符串中多次搜索更快(从根本上说):实际上,使用正则表达式时,序列最多只能读取一次(而不是字母的两次)没有找到,例如gnibbler的原始答案)。使用gnibbler的memoization,正则表达式方法如下:

import re
remove = re.compile('[XN]').search

codon = ['AAT','XAC','ANT','TTA']
def pred(s,memo={}):
    if s not in memo:
        memo[s]= not remove(s)
    return memo[s]

print filter(pred,codon)

这应该(渐近地)比使用“in s”或“set”检查更快(即,对于足够长的字符串s,上面的代码应该更快。)

我原本以为gnibbler的答案可以用dict.setdefault()以更快,更紧凑的方式编写:

codon = ['AAT','XAC','ANT','TTA']
def pred(s,memo={}):
    return memo.setdefault(s, not any(y in s for y in "XN"))

print filter(pred,codon)

然而,正如gnibbler所指出的那样,总是会评估setdefault中的值(即使原则上只有在找不到字典键时才能评估它。)