2010-03-08 10 views
59

consideri ..Il modo più semplice per sostituire una stringa utilizzando un dizionario di sostituzioni?

dict = { 
'Спорт':'Досуг', 
'russianA':'englishA' 
} 

s = 'Спорт russianA' 

mi piacerebbe sostituire tutte le chiavi dict con i rispettivi valori dict in s.

+0

Questo potrebbe non essere così semplice. Probabilmente dovresti avere un tokenizer esplicito (ad esempio '{'cat': 'russiancat'}' e 'caterpillar'). Anche parole sovrapposte ('{'car': 'russiancar', 'pet': 'russianpet'} 'e' carpet '). – Joe

+2

Vedere anche http://code.activestate.com/recipes/81330-single-pass-multiple-replace/ – ChristopheD

+1

Per inciso: penso che "dict" sia meglio evitare come nome di variabile, perché una variabile di questo nome sarebbe ombreggia la funzione integrata con lo stesso nome. – jochen

risposta

76

Utilizzando Re:

import re 

s = 'Спорт not russianA' 
d = { 
'Спорт':'Досуг', 
'russianA':'englishA' 
} 

pattern = re.compile(r'\b(' + '|'.join(d.keys()) + r')\b') 
result = pattern.sub(lambda x: d[x.group()], s) 
# Output: 'Досуг not englishA' 

Questo selezionerà solo parole intere. Se non avete bisogno di questo, utilizzare il modello:

pattern = re.compile('|'.join(d.keys())) 

Si noti che in questo caso si dovrebbe ordinare le parole che discendono dalla lunghezza, se alcune delle vostre voci del dizionario sono stringhe degli altri.

+18

Nel caso in cui le chiavi del dizionario contengano caratteri come "^", "$" e "/", le chiavi devono essere precedute da caratteri di escape prima che venga assemblata l'espressione regolare. questo, '.join (d.keys())' potrebbe essere sostituito da '.join (re.escape (chiave) per la chiave in d.keys())'. – jochen

+0

Si noti che il primo esempio (Досуг non ingleseA) funziona solo in python3. In python2 mi viene ancora restituito "Спорт not englishA" –

5

unidirezionale, senza ri

d = { 
'Спорт':'Досуг', 
'russianA':'englishA' 
} 

s = 'Спорт russianA'.split() 
for n,i in enumerate(s): 
    if i in d: 
     s[n]=d[i] 
print ' '.join(s) 
+2

Questo fallirà se il dict ha spazio nelle sue chiavi –

3

Quasi uguale ghostdog74, se creato autonomamente. Una differenza, utilizzando d.get() invece di d [] può gestire elementi non presenti in dict.

>>> d = {'a':'b', 'c':'d'} 
>>> s = "a c x" 
>>> foo = s.split() 
>>> ret = [] 
>>> for item in foo: 
... ret.append(d.get(item,item)) # Try to get from dict, otherwise keep value 
... 
>>> " ".join(ret) 
'b d x' 
21

È possibile utilizzare la funzione reduce:

reduce(lambda x, y: x.replace(y, dict[y]), dict, s) 
+13

Diversamente dalla soluzione di @Max Shawabkeh, usando 'reduce' si applicano le sostituzioni una dopo l'altra. Di conseguenza, scambiando le parole usando i dizionari '{'rosso': 'verde', 'verde': 'rosso'}' non funziona con l'approccio 'reduce' e le corrispondenze sovrapposte vengono trasformate in modo imprevedibile. – jochen

+1

Un buon esempio del perché ripetute chiamate '.replace()' possono avere conseguenze non intenzionali: 'html.replace ('"' ',' " ') .replace (' & ',' & ') '-inseriscilo su' html = '"foo"' '. – zigg

+0

Questo è inutilmente complesso e illeggibile rispetto al ciclo spiegato come mostrato nelle risposte di [ChristopheD] (https://stackoverflow.com/a/2401481/216074) o [user2769207] (https : //stackoverflow.com/a/18748467/216074). – poke

16

Solution found here (mi piace la sua semplicità):

def multipleReplace(text, wordDict): 
    for key in wordDict: 
     text = text.replace(key, wordDict[key]) 
    return text 
+8

Anche in questo caso, come descritto da @jochen, si rischia una traduzione errata se esiste una chiave che è anche un valore. Una sostituzione single-pass sarebbe la migliore. – Chris

1

Ho usato questo in una situazione simile (la mia stringa era tutto in maiuscolo):

def translate(string, wdict): 
    for key in wdict: 
     string = string.replace(key, wdict[key].lower()) 
    return string.upper() 

speranza che aiuta in qualche modo. .. :)

+2

È molto simile alla soluzione di ChristopheD. Sei in disaccordo con lui? – hynekcer

0

con l'avvertimento che viene a mancare se la chiave è lo spazio, questa è una soluzione simile a quella compressa ghostdog74 e extaneons risposte:

d = { 
'Спорт':'Досуг', 
'russianA':'englishA' 
} 

s = 'Спорт russianA' 

' '.join(d.get(i,i) for i in s.split()) 
Problemi correlati