2009-06-02 7 views
6

In PHP, si ha preg_replace($patterns, $replacements, $string), in cui è possibile effettuare tutte le sostituzioni contemporaneamente inserendo una serie di motivi e sostituzioni.È possibile passare un dizionario quando si sostituiscono le stringhe in Python?

Qual è l'equivalente in Python?

ho notato che le funzioni di stringa e ri replace() e sub() non prendono dizionari ...

A cura di chiarire sulla base di un commento di rick: l'idea è di avere un dict con le chiavi da prendere come modelli di espressioni regolari, come ad esempio '\d+S' e (si spera) i valori di stringa costante (si spera senza backreferences). Ora modifica la mia risposta di conseguenza (cioè per rispondere alla domanda reale).

risposta

10

più vicino è probabilmente:

somere.sub(lambda m: replacements[m.group()], text) 

ad esempio:

>>> za = re.compile('z\w') 
>>> za.sub(lambda m: dict(za='BLU', zo='BLA')[m.group()], 'fa za zo bu') 
'fa BLU BLA bu' 

con un .get invece di [] -indexing se si vuole fornire un default per le partite che mancano in replacements.

Edit: ciò rick vuole davvero è quello di avere un dict con le chiavi per essere presi come modelli di espressioni regolari, come ad esempio '\d+S', e (si spera) costanti i valori di stringa (si spera w/o backreference). La ricetta ricettario può essere adattata per questo scopo: uso

def dict_sub(d, text): 
    """ Replace in 'text' non-overlapping occurences of REs whose patterns are keys 
    in dictionary 'd' by corresponding values (which must be constant strings: may 
    have named backreferences but not numeric ones). The keys must not contain 
    anonymous matching-groups. 
    Returns the new string.""" 

    # Create a regular expression from the dictionary keys 
    regex = re.compile("|".join("(%s)" % k for k in d)) 
    # Facilitate lookup from group number to value 
    lookup = dict((i+1, v) for i, v in enumerate(d.itervalues())) 

    # For each match, find which group matched and expand its value 
    return regex.sub(lambda mo: mo.expand(lookup[mo.lastindex]), text) 

Esempio:

d={'\d+S': 'wot', '\d+T': 'zap'} 
    t='And 23S, and 45T, and 66T but always 029S!' 
    print dict_sub(d, t) 

emette:

And wot, and zap, and zap but always wot! 

Si potrebbe evitare la costruzione lookup e basta usare mo.expand(d.values()[mo.lastindex-1]), ma che potrebbe essere un po 'lento se d è molto grande e ci sono molte corrispondenze (mi dispiace, non ho misurato con precisione/benchmark entrambi gli approcci, quindi questo è solo una supposizione;-).

+0

Questo supporta solo un'espressione regolare, penso che si può Andare più semplice della funzione che ho preso da ActiveState nel caso in cui in realtà si desidera sia una sostituzione e un pattern dettato. Puoi? –

+0

Per eseguire diverse sostituzioni di stringhe in una passata, mi piace quella ricetta, ecco perché l'ho scelta per il Cookbook di Python, vedi http://books.google.com/books?id=Q0s6Vgb98CQC&pg=PA38&dq=xavier+defrang&ei=k5okSvPbNILClQSk2LWvBw (Penso che la discussione che Anna e io abbiamo aggiunto aggiunga qualche valore, ma ovviamente sono di parte). Stavo cercando di rispondere più direttamente alla domanda esatta - una RE completamente generale e un dittato di sostituzioni. –

+0

Penso che la risposta alla domanda originale sia la ricetta, perché il preg_replace di PHP accetta sia regex che sostituzioni. –

-2

E 'abbastanza semplice per farlo:

replacements = dict(hello='goodbye', good='bad') 
s = "hello, good morning"; 
for old, new in replacements.items(): 
    s = s.replace(old, new) 

Troverete molti posti dove le funzioni PHP accettano una matrice di valori e non c'è Python equivalente diretto, ma è molto più facile lavorare con le matrici (liste) in Python quindi è meno di un problema.

+0

potresti voler usare dict.iteritems invece di dict.items, per PEP290 http://www.python.org/dev/peps/pep- 0290/# looping-over-dictionaries – NicDumZ

+5

Non mi piace. non è garantito che dict.items() sia in un ordine particolare, quindi la sostituzione risultante è imprevedibile. Ad esempio, nel tuo esempio, se "hello" viene elaborato per primo, la stringa risultante è "badbye, bad morning"; altrimenti, è "addio, brutta mattinata". – Triptych

+0

@Triptych: bella cattura. –

-1

Ecco un modo semplice utilizzando ridurre

mynewstring=reduce(lambda a,(b,c): a.replace(b, c), mydict.items(), mystring) 
+0

Che fallisce se mydict è '{'a': 'b', 'b': 'a'}' – Eric

+0

@Eric questo è un prezzo che paghiamo per essere semplice. questo modo semplice simula sostituzioni concatenate. –

+1

Una soluzione semplice è inutile se non funziona anche – Eric

-2

È possibile passare il dizionario durante la sostituzione di stringa in Python. Si consideri l'esempio di cui sopra:

replacement = {'hello' : 'goodbye', 'good' : 'bad' } 

avete scrivere la stringa in questo formato

s = "%(hello)s, %(good)s morning" 
changed_s = s%replacement 

l'uscita di changed_s sarà

"goodbye, bad morning" 
+1

-1: Quello non è la sostituzione di stringhe, la sua interpolazione di stringa. – Blair

Problemi correlati