2009-06-02 12 views
6

En PHP, tiene preg_replace($patterns, $replacements, $string), donde puede hacer todas sus sustituciones a la vez pasando una gran variedad de patrones y reemplazos.¿Se puede pasar un diccionario al reemplazar cadenas en Python?

¿Cuál es el equivalente en Python?

me di cuenta de que las funciones de cadena y re replace() y sub() no toman diccionarios ...

Editado para aclarar sobre la base de un comentario por Rick: la idea es tener un diccionario con claves a tomar como patrones de expresiones regulares, como '\d+S', y (con suerte) valores de cadena constantes (con suerte sin referencias hacia atrás). Ahora edito mi respuesta en consecuencia (es decir, para responder la pregunta real).

Respuesta

10

más cercano es probablemente:

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

por ejemplo:

>>> 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 en lugar de [] -indexing si desea proporcionar un valor predeterminado para partidos que faltan en replacements.

Editar: lo que Rick realmente quiere es tener un dict con claves para tomarse como patrones de expresiones regulares, como '\d+S', y (con suerte) valores de cadena constantes (con suerte sin referencias hacia atrás). La receta de libro de cocina puede ser adaptado para este fin:

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) 

Ejemplo del uso:

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

emite:

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

Se podría evitar la construcción de lookup y sólo tiene que utilizar mo.expand(d.values()[mo.lastindex-1]), pero que podría ser un poco lento si d es muy grande y hay muchas coincidencias (lo siento, no he medido/evaluado con precisión ambos enfoques, así que esto es Solo una suposición;-).

+0

Esto sólo admite una expresión regular, creo que se puede No es más simple que la función que obtuve de ActiveState en caso de que realmente desee un reemplazo y un dict de patrones. ¿Puedes? –

+0

Para realizar varias sustituciones de cadenas en una sola pasada, me gusta esa receta, es por eso que la elegí para el Python Cookbook, consulte http://books.google.com/books?id=Q0s6Vgb98CQC&pg=PA38&dq=xavier+defrang&ei=k5okSvPbNILClQSk2LWvBw (Creo que la discusión que Anna y yo agregamos agrega cierto valor, pero estoy parcializado por supuesto). Estaba tratando de responder más directamente a la pregunta exacta que se me hizo: una RE completamente general y un dado dado de reemplazos. –

+0

Creo que la pregunta original es mejor respondida por la receta, porque el preg_replace de PHP acepta tanto regexps como reemplazos. –

-2

Es bastante fácil de hacer esto:

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

se pueden encontrar muchos lugares en los que las funciones de PHP aceptan una matriz de valores y no hay un equivalente Python directa, pero es mucho más fácil trabajar con arrays (listas) en Python, por lo que es un problema menor.

+0

es posible que desee utilizar dict.iteritems en lugar de dict.items, según PEP290 http://www.python.org/dev/peps/pep- 0290/# looping-over-dictionaries – NicDumZ

+5

No me gusta. No se garantiza que dict.items() esté en un orden particular, por lo que el reemplazo resultante es impredecible. Por ejemplo, en su ejemplo, si "hello" se procesa primero, la cadena resultante es "adiós, mala mañana"; de lo contrario, es "adiós, malos días". – Triptych

+0

@Triptych: Buena captura. –

-1

Aquí es una forma sencilla usando reducir

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

Eso falla si mydict es '{'a': 'b', 'b': 'a'}' – Eric

+0

@Eric este es un precio que pagamos por ser simple. esta forma simple simula reemplazos encadenados. –

+1

Una solución simple es inútil si tampoco funciona – Eric

-2

Puede pasar el diccionario, mientras que la sustitución de cadenas en Python. Considere el ejemplo anterior:

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

usted tiene escribir la cadena en este formato

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

la salida de changed_s será

"goodbye, bad morning" 
+1

-1: Eso no es reemplazo de cadena, su interpolación de cadena. – Blair

Cuestiones relacionadas