¿Cómo convertir una cadena en un caso de título en Python?

97

Ejemplo:

HILO -> Hilo
new york -> New York
SAN FRANCISCO -> San Francisco

¿Existe una biblioteca o una forma estándar de realizar esta tarea?

soñador
fuente
16
Eso no es "CamelCase", eso es "Capitalizar"; ¿Cuál quieres?
Andrew Marshall
13
camelCase es así.
Jonathan M
5
Sus ejemplos usan PascalCase.
David Betz

Respuestas:

219

¿Por qué no usar titleRight from the docs?

>>> "they're bill's friends from the UK".title()
"They'Re Bill'S Friends From The Uk"

Si realmente deseaba PascalCase, puede usar esto:

>>> ''.join(x for x in 'make IT pascal CaSe'.title() if not x.isspace())
'MakeItPascalCase'
Facundo Casco
fuente
5
Creo que la 'r' en "They're" debería estar en minúsculas. Y la 's' en "Bill's" definitivamente debe ser minúscula.
Daniel Fischer
3
@Daniel: ese problema se menciona en los documentos para title: "El algoritmo usa una definición simple e independiente del lenguaje de una palabra como grupos de letras consecutivas. La definición funciona en muchos contextos, pero significa que los apóstrofes en contracciones y los posesivos forman límites de palabras, que puede no ser el resultado deseado ". Una posible solución sería usar la respuesta de Laurence con la expresión regular r"['\w]+"para que los apóstrofos no terminen una coincidencia (se podría agregar puntuación adicional según sea necesario).
Andrew Clark
18
Para el registro, una forma más ordenada de hacer el último ejemplo de CamelCase es como 'make IT camel CaSe'.title().replace(' ', '').
Henry Gomersall
15
Si alguien más siente que está tomando pastillas locas, este es PascalCase, no camelCase.
Rob
4
Buen código, pero camelCase no comienza con CAPITAL. Prueba esto: def toCamel(s): ret = ''.join(x for x in s.title() if not x.isspace()) return ret[0].lower() + ret[1:] Uso:toCamel("WRITE this in camelcase") 'writeThisInCamelcase'
Ron Kalian
22

Este siempre comenzaría con minúsculas y también eliminaría los caracteres no alfanuméricos:

def camelCase(st):
    output = ''.join(x for x in st.title() if x.isalnum())
    return output[0].lower() + output[1:]
Ivan Chaer
fuente
8
def capitalizeWords(s):
  return re.sub(r'\w+', lambda m:m.group(0).capitalize(), s)

re.subpuede tomar una función para el "reemplazo" (en lugar de solo una cadena, que es el uso con el que la mayoría de la gente parece estar familiarizada). Esta función de respuesta se llamará con un re.Matchobjeto para cada coincidencia del patrón, y el resultado (que debería ser una cadena) se utilizará como reemplazo para esa coincidencia.

Una versión más larga de lo mismo:

WORD_RE = re.compile(r'\w+')

def capitalizeMatch(m):
  return m.group(0).capitalize()

def capitalizeWords(s):
  return WORD_RE.sub(capitalizeMatch, s)

Esto precompila el patrón (generalmente considerado de buena forma) y usa una función con nombre en lugar de una lambda.

Laurence Gonsalves
fuente
este es bastante bueno, estoy tratando de entender las funciones lambda, gracias por ayudar
daydreamer
1
@JohnMachin Acabo de preguntar porque pensé que agregar alguna explicación haría que tu respuesta fuera más completa y mejor.
NN
@Laurence Gonsalves, ¿qué hace lambda aquí?
Zion
que esta haciendo lambda aqui? de lo que puedo descifrar y de tu explicación. esto es lo que entendí. cuando usa una función en re.sub, ¿cada una se matchpasará a la función? y dado que matchesen las expresiones regulares tienen grupos. por eso existe esta línea lambda m:m.group(0).capitalize()?
Sion
@ Zion sí. Cuando re.subse le da un invocable (por ejemplo: una función) como "reemplazo", pasa el objeto de coincidencia al invocable, y espera recuperar una cadena que es lo que realmente usa como reemplazo. Si encuentra que las lambdas son confusas, la "versión más larga" hace exactamente lo mismo de una manera más detallada.
Laurence Gonsalves
5

¿Por qué no escribes uno? Algo como esto puede satisfacer sus requisitos:

def FixCase(st):
    return ' '.join(''.join([w[0].upper(), w[1:].lower()]) for w in st.split())
múltiples interfaces
fuente
gracias, eso ayudó completamente. Mi mal, no pensé en escribir uno en primer lugar
Daydreamer
5

Nota: ¿Por qué estoy dando otra respuesta? Esta respuesta se basa en el título de la pregunta y en la noción de que camelcase se define como: una serie de palabras que se han concatenado (¡sin espacios!) De modo que cada una de las palabras originales comience con una letra mayúscula (el resto en minúsculas) excepto la primera palabra de la serie (que está completamente en minúsculas). También se supone que "todas las cadenas" se refiere al conjunto de caracteres ASCII; unicode no funcionaría con esta solución).

sencillo

Dada la definición anterior, esta función

import re
word_regex_pattern = re.compile("[^A-Za-z]+")

def camel(chars):
  words = word_regex_pattern.split(chars)
  return "".join(w.lower() if i is 0 else w.title() for i, w in enumerate(words))

, cuando se llama, resultaría de esta manera

camel("San Francisco")  # sanFrancisco
camel("SAN-FRANCISCO")  # sanFrancisco
camel("san_francisco")  # sanFrancisco

menos simple

¡Tenga en cuenta que falla cuando se presenta con una cadena ya envuelta en camello!

camel("sanFrancisco")   # sanfrancisco  <-- noted limitation

aún menos simple

Tenga en cuenta que falla con muchas cadenas Unicode

camel("México City")    # mXicoCity     <-- can't handle unicode

No tengo una solución para estos casos (u otros que podrían introducirse con algo de creatividad). Entonces, como en todas las cosas que tienen que ver con cadenas, ¡cubra sus propios casos extremos y buena suerte con Unicode!

Bagazo
fuente
¿Cómo se puede determinar que una cadena es un caso Camel sin conocer el significado de la oración? En su ejemplo "menos simple", "sanfRancisco" es el caso Camel así como "itSnotcaMelcAse".
Patrice Bernassola
¿Supongo que su entrada tenía apostrafios u otra puntuación? Debo notar otra entrada fallida. Definitivamente una buena captura. ¿Cuál fue la información que proporcionó?
Marc
1
Quiero decir que una secuencia de caracteres sin espacios debe considerarse como 1 palabra. No se puede extraer trabajo de él sin conocer el significado de la oración. Pon "sanfRancisco" o "itSnotcaMelcAse" como entrada de camello () y verás que la salida será la misma.
Patrice Bernassola
Oh, ya veo, sí, creo que tienes razón. Yo superpongo la solución. Lo actualizaré.
Marc
4

Biblioteca potencial: https://pypi.org/project/stringcase/

Ejemplo:

import stringcase
stringcase.camelcase('foo_bar_baz') # => "fooBarBaz"

Aunque es cuestionable si dejará espacios adentro (los ejemplos muestran que quita espacio, pero hay un problema de seguimiento de errores que indica que los deja adentro).

Jajaja
fuente
Diablos, sí. Estaba buscando un paquete. Este paquete tiene snakecase y otras funciones de conversión también.
s2t2
1

solo use .title (), y convertirá la primera letra de cada palabra en mayúscula, resto en pequeño:

>>> a='mohs shahid ss'
>>> a.title()
'Mohs Shahid Ss'
>>> a='TRUE'
>>> b=a.title()
>>> b
'True'
>>> eval(b)
True
Mohammad Shahid Siddiqui
fuente
1

Me gustaría agregar mi pequeña contribución a esta publicación:

def to_camelcase(str):
  return ' '.join([t.title() for t in str.split()])
Evhz
fuente
En realidad, str.title () es el mismo y está ahorrando costos computacionales.
Auros132
1
def camelCase(st):
    s = st.title()
    d = "".join(s.split())
    d = d.replace(d[0],d[0].lower())
    return d
Aishwarya Skandamani
fuente