2013-04-02 24 views
5

Nel mio programma ho una stringa come questa:Mantenere solo determinati caratteri in una stringa usando Python?

ag ct oso gcota

con Python, il mio obiettivo è quello di sbarazzarsi dello spazio bianco e mantenere solo le a, caratteri T, C, e g . Capisco come liberarmi dello spazio bianco (sto solo usando line = line.replace ("", "")). Ma come posso liberarmi dei personaggi di cui non ho bisogno quando potrebbero essere qualsiasi altra lettera dell'alfabeto?

risposta

12

Un modo molto elegante e veloce è quello di utilizzare le espressioni regolari:

import re 

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

"""str is now 'agctgcta""" 
+0

Hai vinto :) (+1). Non so perché non ho pensato a regex per questo ... – mgilson

+0

Ho fatto +1 anche a te. La seconda soluzione che hai fornito (str.translate) era nuova per me :) –

4

potrei fare qualcosa di simile:

chars_i_want = set('atcg') 
final_string = ''.join(c for c in start_string if c in chars_i_want) 

Questo è probabilmente il modo più semplice per farlo.


Un'altra opzione sarebbe quella di utilizzare str.translate per fare il lavoro:

import string 
chars_to_remove = string.printable.translate(None,'acgt') 
final_string = start_string.translate(None,chars_to_remove) 

non sono sicuro che sarebbe un rendimento migliore. Dovrebbe essere cronometrato via timeit per sapere in modo definitivo.


aggiornamento: Tempi!

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)) 

Purtroppo (per me), regex vince sulla mia macchina:

test_re 0.901512145996 
test_join1 6.00346088409 
test_join2 3.66561293602 
translate 1.0741918087 
+0

l'uso di regex.sub() non è corretto, e quindi il tempo è sbagliato. Dovrebbe essere regex.sub ('', s) e non viceversa. –

0

Did test_re persone di prova di mgilson() prima delle upvoting? Gli argomenti a re.sub() vengono annullati, quindi stava facendo la sostituzione in una stringa vuota e restituisce sempre una stringa vuota.

Lavoro in python 3.4; string.translate() accetta solo un argomento, un dettato. Poiché c'è un sovraccarico nella costruzione di questo ditt, l'ho spostato fuori dalla funzione. Per essere onesti, ho anche spostato la compilazione regex dalla funzione (questo non ha fatto una differenza evidente).

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))) 

Qui ci sono i tempi:

test_re 3.3141989699797705 
test_join1 2.4452173250028864 
test_join2 2.081048655003542 
translate 1.9390292020107154 

Peccato string.translate() non ha la possibilità di controllare che cosa fare con caratteri che non sono nella mappa. L'implementazione attuale è di mantenerli, ma potremmo anche avere la possibilità di rimuoverli, nei casi in cui i personaggi che vogliamo mantenere siano molto meno numerosi di quelli che vogliamo rimuovere (oh ciao, unicode).

Problemi correlati