使用Python在字符串中只保留某些字符?

2024-05-08 01:04:53 发布

您现在位置:Python中文网/ 问答频道 /正文

在我的程序中,我有一个这样的字符串:

ag-ct-oso-gcota公司

使用python,我的目标是去掉空白,只保留a、t、c和g字符。 我知道如何去掉空白(我只是使用line=line.replace(“,”))。但是,当我不需要的字符可以是字母表中的任何其他字母时,我怎样才能去掉它们呢?


Tags: 字符串程序目标字母line公司字符空白
3条回答

我可能会这样做:

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

一个非常优雅和快速的方法是使用正则表达式:

import re

str = 'ag ct oso gcota'
str = re.sub('[^atcg]', '', str)

"""str is now 'agctgcta"""

人们在投票前测试过mgilson的test_re()函数吗?re.sub()的参数是相反的,因此它在空字符串中进行替换,并始终返回空字符串。

我在Python3.4中工作;string.translate()只接受一个参数dict,因为构建这个dict有开销,所以我将它从函数中移出。公平地说,我还将regex编译从函数中移出(这没有明显的区别)。

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

字符串太糟糕了。translate()没有选项来控制如何处理不在映射中的字符。当前的实现是保留它们,但我们也可以选择删除它们,以防我们要保留的字符远少于要删除的字符(哦,hello,unicode)。

相关问题 更多 >