2011-09-06 11 views
7

Soy nuevo en Python y estoy tratando de reemplazar todas las mayúsculas-letras dentro de una palabra de subrayado, por ejemplo:Cómo reemplazar mayúsculas con guiones bajos?

ThisIsAGoodExample 

debe convertirse en

this_is_a_good_example 

Cualquier ideas/consejos/enlaces/tutoriales sobre cómo lograr esto?

+3

http://stackoverflow.com/questions/1175208/does-the-python-standard-library-have-function-to-convert-camelcase-to-camel-case –

+0

El ejemplo que da no coincide ni con el título ni con el título la descripción de esta pregunta. ¿Está tratando de reemplazar todos los caracteres en mayúsculas con guiones bajos o está tratando de convertir CamelCase a lowercase_underscore_separated? Descubrirá que a menos que pueda explicar en palabras qué es lo que quiere hacer, resolverlo en Python (o en cualquier otro idioma) será demasiado desafiante. – Johnsyweb

Respuesta

0

Analizar la cadena, cada vez que se encuentra con una letra mayúscula, insertar una _ antes y después cambiar el carácter encontrado a minúsculas

+0

(excepto el primero) – rplnt

+0

¿Qué pasa con el primer carácter en mayúsculas? – Johnsyweb

+0

@rplnt - Dado que su verborrea no coincide con su ejemplo, fui con la verborrea – KevinDTimm

8
import re 
"_".join(l.lower() for l in re.findall('[A-Z][^A-Z]*', 'ThisIsAGoodExample')) 

EDIT: En realidad, esto sólo funciona si la primera la letra es mayúscula De lo contrario esto (tomado de here) hace lo correcto:

def convert(name): 
    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) 
    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() 
+0

Tómelo con calma en el novato. :) –

2
example = 'ThisIsAGoodExample' 
# Don't put an underscore before first character. 
new_example = example[0] 
for character in example[1:]: 
    # Append an underscore if the character is uppercase. 
    if character.isupper(): 
     new_example += '_' 
    new_example += character.lower() 
+1

Reemplace la línea 6 con 'if character.isupper()' que (debería) manejar unicode, también. –

+0

@Kirk, gracias. Fijo. –

10

Aquí está una manera de expresiones regulares:

import re 
example = "ThisIsAGoodExample" 
print re.sub('(?<!^)(?=[A-Z])', '_', example).lower() 

Esto es decir, "Encontrar puntos en la cadena que no son precedido por un inicio de línea, y son seguidos de un carácter en mayúsculas y sustituyen un guión bajo. A continuación, bajamos() el caso en su totalidad.

+2

Que echa de menos muchas letras mayúsculas. No manejaría una ortografía de mi nombre, "Éric", por ejemplo. IIRC, '\ p {Lu}' es el patrón apropiado, no '[A-Z]'. – ikegami

1

Como nadie más ha ofrecido una solución utilizando un generador, aquí está uno:

>>> sample = "ThisIsAGoodExample" 
>>> def upperSplit(data): 
... buff = '' 
... for item in data: 
...  if item.isupper(): 
...  if buff: 
...   yield buff 
...   buff = '' 
...  buff += item 
... yield buff 
... 
>>> list(upperSplit(sample)) 
['This', 'Is', 'A', 'Good', 'Example'] 
>>> "_".join(upperSplit(sample)).lower() 
'this_is_a_good_example' 
4

Esto genera una lista de elementos, donde cada elemento es "_" seguido de la letra en minúsculas si el personaje era originalmente una letra mayúscula, o el personaje en sí mismo si no fuera así. Luego se los une en una cadena y elimina subrayado iniciales que podrían haber sido añadidos por el proceso:

print ''.join('_' + char.lower() if char.isupper() else char 
       for char in inputstring).lstrip('_') 

Por cierto, no se han especificado qué hacer con guiones que ya están presentes en la cadena. No estaba seguro de cómo manejar ese caso, así que di un puntapié.

Cuestiones relacionadas