在我的程序中,我有一个像这样的字符串:
'ag ct oso gcota'
使用 python,我的目标是摆脱空格并仅保留 a、t、c 和 g 字符。 我知道如何消除空白(我只是使用
line = line.replace(" ", "")
)。但是,当我不需要的字符可能是字母表中的任何其他字母时,我该如何删除它们呢?
一个非常优雅且快速的方法是使用正则表达式:
>>> import re
>>> s = 'ag ct oso gcota'
>>> re.sub('[^atcg]', '', s)
'agctgcta'
我可能会做这样的事情:
chars_i_want = set('atcg')
final_string = ''.join(c for c in start_string if c in chars_i_want)
这可能是最简单的方法。
另一种选择是使用
str.translate
来完成这项工作:
import string
chars_to_remove = string.printable.translate(None,'acgt')
final_string = start_string.translate(None,chars_to_remove)
我不确定哪个效果更好。需要通过
timeit
计时才能确切知道。
更新:时间安排!
import re
import string
def test_re(s,regex=re.compile('[^atgc]')):
return regex.sub(s,'')
def test_join1(s,chars_keep=set('atgc')):
return ''.join(c for c in s if c in chars_keep)
def test_join2(s,chars_keep=set('atgc')):
""" list-comp is faster, but less 'idiomatic' """
return ''.join([c for c in s if c in chars_keep])
def translate(s,chars_to_remove = string.printable.translate(None,'acgt')):
return s.translate(None,chars_to_remove)
import timeit
s = 'ag ct oso gcota'
for func in "test_re","test_join1","test_join2","translate":
print func,timeit.timeit('{0}(s)'.format(func),'from __main__ import s,{0}'.format(func))
可悲的是(对我来说),
regex
在我的机器上获胜:
test_re 0.901512145996
test_join1 6.00346088409
test_join2 3.66561293602
translate 1.0741918087
人们在投票之前测试过 mgilson 的 test_re() 函数吗? re.sub() 的参数是相反的,因此它在空字符串中进行替换,并且始终返回空字符串。
我使用Python 3.4; string.translate() 仅接受一个参数,即一个字典。因为构建这个字典会产生开销,所以我将其从函数中移出。公平地说,我还将正则表达式编译移出了函数(这并没有产生明显的差异)。
import re
import string
regex=re.compile('[^atgc]')
chars_to_remove = string.printable.translate({ ord('a'): None, ord('c'): None, ord('g'): None, ord('t'): None })
cmap = {}
for c in chars_to_remove:
cmap[ord(c)] = None
def test_re(s):
return regex.sub('',s)
def test_join1(s,chars_keep=set('atgc')):
return ''.join(c for c in s if c in chars_keep)
def test_join2(s,chars_keep=set('atgc')):
""" list-comp is faster, but less 'idiomatic' """
return ''.join([c for c in s if c in chars_keep])
def translate(s):
return s.translate(cmap)
import timeit
s = 'ag ct oso gcota'
for func in "test_re","test_join1","test_join2","translate":
print(func,timeit.timeit('{0}(s)'.format(func),'from __main__ import s,{0}'.format(func)))
具体时间如下:
test_re 3.3141989699797705
test_join1 2.4452173250028864
test_join2 2.081048655003542
translate 1.9390292020107154
太糟糕了 string.translate() 没有选项来控制如何处理不在地图中的字符。当前的实现是保留它们,但如果我们要保留的字符远少于我们要删除的字符(哦,你好,unicode),我们也可以选择删除它们。