L'esempio specifico si danno (l'eliminazione di singoli caratteri) è perfetto per il metodo translate
di stringhe, come la sostituzione di singoli caratteri con caratteri singoli. Se la stringa di input è di tipo Unicode, quindi, oltre ai due suddetti tipi di "sostituzione", la sostituzione di singoli caratteri con più stringhe di caratteri è ugualmente valida con il metodo translate
(non se è necessario lavorare su stringhe di byte, sebbene).
Se è necessario sostituire sottostringhe di più caratteri, quindi consiglierei anche utilizzando un'espressione regolare - anche se non in risposta al modo di @ gnibbler raccomanda; piuttosto, vorrei costruire la regex da r'onestring|another|yetanother|orthis'
(unire le sottostringhe che si desidera sostituire con barre verticali - assicuratevi di anche re.escape
se contengono caratteri speciali, ovviamente) e scrivete una semplice funzione di sostituzione basata su un dict.
Non ho intenzione di offrire un sacco di codice in questo momento poiché non so quale dei due paragrafi si applica alle vostre reali esigenze, ma (quando torno più tardi a casa e controllo di nuovo ;-) Sarò lieto di modificare per aggiungere un esempio di codice in base alle tue modifiche alla tua domanda (più utile dei commenti a questa risposta ;-).
Edit: in un commento del PO dice che vuole una risposta "più generale" (senza chiarire che cosa ciò significhi), poi in una modifica del suo Q dice che vuole studiare i "compromessi" tra i vari frammenti tutti i dei quali usano sottostringhe a carattere singolo (e ne controllano la presenza, piuttosto che la sostituzione come richiesto originariamente - semantica completamente diversa, ovviamente).
Dato questo totale e completa confusione tutto quello che posso dire è che al "check compromessi" (performance-saggio) Mi piace usare python -mtimeit -s'setup things here' 'statements to check'
(assicurandosi che le dichiarazioni di controllare non hanno effetti collaterali, per non inficiare le misure di tempo, dal momento che timeit
loop implicitamente per fornire misurazioni precise della tempistica).
una risposta generale (senza compromessi, e coinvolgendo sottostringhe multiple caratteri, in modo del tutto contrario alla sua modifica di Q, ma consonanti per i suoi commenti - i due essendo del tutto contraddittorio che è ovviamente impossibile da soddisfare entrambi): uso
import re
class Replacer(object):
def __init__(self, **replacements):
self.replacements = replacements
self.locator = re.compile('|'.join(re.escape(s) for s in replacements))
def _doreplace(self, mo):
return self.replacements[mo.group()]
def replace(self, s):
return self.locator.sub(self._doreplace, s)
esempio:
r = Replacer(zap='zop', zip='zup')
print r.replace('allazapollezipzapzippopzip')
Se alcune delle stringhe da sostituire sono le parole chiave di Python, hanno bisogno di essere passati in un po 'meno direttamente, ad esempio,, Il seguente:
r = Replacer(abc='xyz', def='yyt', ghi='zzq')
sarebbe falliscono perché def
è una parola chiave, quindi è necessario ad es .:
r = Replacer(abc='xyz', ghi='zzq', **{'def': 'yyt'})
o simili.
Trovo che questo sia un buon uso per una classe (piuttosto che una programmazione procedurale) perché la RE per individuare le sottostringhe da sostituire, il dict che esprime cosa sostituirle e il metodo che esegue la sostituzione, in realtà grida di essere "mantenuto tutto insieme", e un'istanza di classe è il modo giusto per eseguire un "mantenimento insieme" in Python. Una fabbrica chiusura avrebbe anche funzionato (in quanto il metodo replace
è in realtà l'unica parte dell'istanza che esigenze siano visibili "fuori"), ma in un forse meno evidente, più difficili da eseguire il debug modo:
def make_replacer(**replacements):
locator = re.compile('|'.join(re.escape(s) for s in replacements))
def _doreplace(mo):
return replacements[mo.group()]
def replace(s):
return locator.sub(_doreplace, s)
return replace
r = make_replacer(zap='zop', zip='zup')
print r('allazapollezipzapzippopzip')
L'unico vero vantaggio potrebbe essere una prestazione molto modestamente migliore (deve essere controllato con timeit
su "casi di riferimento" considerati significativi e rappresentativi per l'app che lo utilizza) come accesso alle "variabili libere" (replacements
, locator
, _doreplace
) in questo caso potrebbe essere molto più veloce dell'accesso ai nomi qualificati (self.replacements
ecc.) nel normale approccio basato sulla classe (se questo è il caso dipenderà dall'implementazione Python in uso, da cui la necessità di verificare con timeit
su benchmark significativi!).
Non sono sicuro di come si intende utilizzare una tabella di ricerca: quali sono le chiavi e i valori? Inoltre, il tuo esempio ha alcuni refusi/incongruenze. – zdav
Dove sono gli errori di battitura? Ho usato un'ellissi per troncare l'esempio per la leggibilità. –