我想从列表中删除元素,以便元素包含'X'
或'N'
。我必须申请大型基因组。这是一个例子:
输入:
codon=['AAT','XAC','ANT','TTA']
预期产出:
codon=['AAT','TTA']
答案 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)
filter(lambda x: 'N' not in x or 'X' not in x, your_list)
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中的值(即使原则上只有在找不到字典键时才能评估它。)