¿Cómo poner en mayúscula la primera letra de cada palabra en una cadena?

Respuestas:

991

El .title()método de una cadena (ya sea ASCII o Unicode está bien) hace esto:

>>> "hello world".title()
'Hello World'
>>> u"hello world".title()
u'Hello World'

Sin embargo, busque cadenas con apóstrofes incrustados, como se señala en los documentos.

El algoritmo utiliza una definición simple de una palabra independiente del idioma como grupos de letras consecutivas. La definición funciona en muchos contextos, pero significa que los apóstrofes en las contracciones y posesivos forman límites de palabras, que pueden no ser el resultado deseado:

>>> "they're bill's friends from the UK".title()
"They'Re Bill'S Friends From The Uk"
Mark Rushakoff
fuente
56
Evito el problema posesivo con algo como" ".join(w.capitalize() for w in s.split())
Evito mehtunguh
3
esto no es seguro para la mayoría de las cadenas porque cada palabra incluso posesiva se pone en mayúscula.
10
Hay un problema con string.title (). Cuando usa, por ejemplo "e g 3b", el resultado deseado sería "E G 3b". Sin embargo, "e g 3b".title()vuelve "E G 3B".
Sören
77
Tenga en cuenta que esto también causará esto:In [2]: 'tEst'.title() Out[2]: 'Test'
Jonas Libbrecht
44
Gran respuesta, y los comentarios destacan que en Python no todo se comporta de la manera que lo necesita, pero siempre hay formas convenientes de hacerlo. La forma más conveniente es a menudo importar una biblioteca especialmente diseñada, como python-titlecase
Aaron3468
189

El .title()método no puede funcionar bien

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

string.capwords()Método de prueba ,

import string
string.capwords("they're bill's friends from the UK")
>>>"They're Bill's Friends From The Uk"

De los documentos de Python en capwords :

Divide el argumento en palabras usando str.split (), escribe cada palabra en mayúscula usando str.capitalize () y une las palabras en mayúscula usando str.join (). Si el segundo argumento opcional sep está ausente o Ninguno, las series de caracteres de espacios en blanco se reemplazan por un solo espacio y los espacios en blanco iniciales y finales se eliminan; de lo contrario, sep se usa para dividir y unir las palabras.

Chen Houwu
fuente
2
Todavía falta Capwords y no maneja algo como "There once was a string with an 'that had words right after it and then closed'". Con este ejemplo, todos los mundos excepto thatse capitalizan como se esperaba. Los resultados son"There Once Was A String With An 'that Had Words Right After It And Then Closed'"
devonbleibtrey
Aún así, esto funciona mejor que title()en situaciones normales. En mi situación, title()devuelve una salida incorrecta para nombres con acentos o diéresis, mientras se capwords()maneja correctamente.
houcros
1
Bien, pero todavía arruina la distinción "Reino Unido / Reino Unido"
Jonath P
1
@Chen Houwu, Reino Unido / Reino Unido es un contraejemplo perfecto. ¿Cómo podría uno evitar que Python ponga en minúsculas las mayúsculas existentes usando un método similar?
h0r53 hace
105

Solo porque este tipo de cosas es divertido para mí, aquí hay dos soluciones más.

Divídase en palabras, encierre en mayúsculas cada palabra de los grupos divididos y vuelva a unirse. Esto cambiará el espacio en blanco que separa las palabras en un solo espacio en blanco, sin importar lo que sea.

s = 'the brown fox'
lst = [word[0].upper() + word[1:] for word in s.split()]
s = " ".join(lst)

EDITAR: No recuerdo lo que estaba pensando cuando escribí el código anterior, pero no hay necesidad de crear una lista explícita; podemos usar una expresión generadora para hacerlo de manera perezosa. Así que aquí hay una mejor solución:

s = 'the brown fox'
s = ' '.join(word[0].upper() + word[1:] for word in s.split())

Use una expresión regular para que coincida con el comienzo de la cadena, o palabras de separación de espacios en blanco, más un solo carácter que no sea un espacio en blanco; use paréntesis para marcar "grupos de coincidencia". Escriba una función que tome un objeto de coincidencia y devuelva el grupo de coincidencia de espacios en blanco sin cambios y el grupo de coincidencia de caracteres sin espacios en blanco en mayúsculas. Luego use re.sub()para reemplazar los patrones. Este no tiene los problemas de puntuación de la primera solución, ni rehace el espacio en blanco como mi primera solución. Este produce el mejor resultado.

import re
s = 'the brown fox'

def repl_func(m):
    """process regular expression match groups for word upper-casing problem"""
    return m.group(1) + m.group(2).upper()

s = re.sub("(^|\s)(\S)", repl_func, s)


>>> re.sub("(^|\s)(\S)", repl_func, s)
"They're Bill's Friends From The UK"

Me alegro de haber investigado esta respuesta. ¡No tenía idea de que re.sub()podría tomar una función! ¡Puede hacer un procesamiento no trivial re.sub()para producir el resultado final!

steveha
fuente
1
+1 para la solución con rodajas. Necesitaba algo que capitalizara las primeras letras sin alterar la capitalización del resto de las palabras (por ejemplo, Foo se convierte en foo, pero FOO se convierte en fOO). Esto fue perfecto.
TomNysetvold
1
capitalize devuelve su primer carácter en mayúscula y el resto en minúscula
Vanuan
@Vanuan, tienes razón! La descripción de la cadena de documentación me hizo pensar que todo lo que hizo fue poner en mayúscula la primera letra, pero tiene razón sobre lo que realmente hace. Editaré la respuesta. Gracias por el aviso.
steveha
Esto parece ser lo que string.capwordshace, según la documentación en la respuesta de Chen Houwu.
Adrian Keister el
1
Algo a tener en cuenta en la respuesta anterior, en lugar de usar s.split (), creo que es mejor usar s.split (''). Esto se debe a que, en caso de que la cadena tenga algunos espacios dobles y desee mantener esos espacios dobles al unirlos, s.plit ('') lo ayudará a mantener los espacios mientras que s.split () no
manpikin
21

Aquí hay un resumen de las diferentes formas de hacerlo, funcionarán para todas estas entradas:

""           => ""       
"a b c"      => "A B C"             
"foO baR"    => "FoO BaR"      
"foo    bar" => "Foo    Bar"   
"foo's bar"  => "Foo's Bar"    
"foo's1bar"  => "Foo's1bar"    
"foo 1bar"   => "Foo 1bar"     

- La solución más simple es dividir la oración en palabras y poner en mayúscula la primera letra y luego volver a unirla:

# Be careful with multiple spaces, and empty strings
# for empty words w[0] would cause an index error, 
# but with w[:1] we get an empty string as desired
def cap_sentence(s):
  return ' '.join(w[:1].upper() + w[1:] for w in s.split(' ')) 

- Si no desea dividir la cadena de entrada en palabras primero y usar generadores elegantes:

# Iterate through each of the characters in the string and capitalize 
# the first char and any char after a blank space
from itertools import chain 
def cap_sentence(s):
  return ''.join( (c.upper() if prev == ' ' else c) for c, prev in zip(s, chain(' ', s)) )

- O sin importar herramientas de iterto:

def cap_sentence(s):
  return ''.join( (c.upper() if i == 0 or s[i-1] == ' ' else c) for i, c in enumerate(s) )

- O puede usar expresiones regulares, de la respuesta de steveha :

# match the beginning of the string or a space, followed by a non-space
import re
def cap_sentence(s):
  return re.sub("(^|\s)(\S)", lambda m: m.group(1) + m.group(2).upper(), s)

Ahora, estas son algunas otras respuestas que se publicaron, y las entradas para las que no funcionan como se esperaba si estamos utilizando la definición de una palabra que es el comienzo de la oración o algo después de un espacio en blanco:

  return s.title()

# Undesired outputs: 
"foO baR"    => "Foo Bar"       
"foo's bar"  => "Foo'S Bar" 
"foo's1bar"  => "Foo'S1Bar"     
"foo 1bar"   => "Foo 1Bar"      

  return ' '.join(w.capitalize() for w in s.split())    
  # or
  import string
  return string.capwords(s)

# Undesired outputs:
"foO baR"    => "Foo Bar"      
"foo    bar" => "Foo Bar"      

usar '' para la división arreglará la segunda salida, pero capwords () aún no funcionará para la primera

  return ' '.join(w.capitalize() for w in s.split(' '))    
  # or
  import string
  return string.capwords(s, ' ')

# Undesired outputs:
"foO baR"    => "Foo Bar"      

Tenga cuidado con múltiples espacios en blanco

  return ' '.join(w[0].upper() + w[1:] for w in s.split())
# Undesired outputs:
"foo    bar" => "Foo Bar"                 
aljgom
fuente
+1 para un resumen completo. Estoy buscando una manera de poner en mayúscula solo una palabra después de un número (no todas las palabras). ¿Podría agregar algo a su respuesta que demuestre esto? Por ejemplo, lower 123 upperdebería volver lower 123 Upper, donde upperse escribe con mayúscula como sigue a un número. Sé que va más allá del alcance de la pregunta del OP, pero es un buen complemento para su respuesta ya extensa. Gracias por adelantado.
ProGrammer
Puede modificar algunos de los métodos anteriores para satisfacer sus necesidades en este caso. Sin embargo, no lo agregaría como parte de la respuesta, ya que no es lo que la mayoría de la gente está buscando. Usaría la versión regex para ella y la usaría en "([0-9]+)(\s+.)"lugar de "(^|\s)(\S)"(hacer coincidir uno o más números, seguido de uno o más espacios y cualquier carácter después), o "([0-9]+)(\s*.)"si desea poner en mayúscula el carácter después de 'cero o más' espacios después de número
aljgom
Me aseguraré de investigarlo, eso me hizo pensar en otro caso especial: ¿Cómo modificaría los fragmentos de arriba para tomar una cadena, por ejemplo, WW1 - the great wary la salida en WW1 - The Great Warlugar de Ww1 ...? ¿Ves el problema con las abreviaturas? ¿Estaría dispuesto a agregar algo que demuestre este caso? Me he estado preguntando sobre esto por un tiempo y no puedo pensar en una forma de hacerlo.
ProGrammer
Las primeras formas indicadas anteriormente no cambian las letras que ya estaban en mayúscula en la cadena de entrada, por WW1lo que saldría comoWW1
aljgom
15

Versión lista para copiar y pegar de @jibberia anwser:

def capitalize(line):
    return ' '.join(s[:1].upper() + s[1:] for s in line.split(' '))
Konstantin Spirin
fuente
2
No es necesario construir una lista. str.joinacepta generadores.
warvariuc
@warvariuc, ¿cómo cambiarías este código para aprovechar los generadores?
Konstantin Spirin
1
Simplemente quite los corchetes, como se hace aquí
warvariuc
1
Aunque @warvariuc es perfecto para mencionar que joinacepta gen exps, en el caso str.joinparticular, generalmente se prefiere usar una lista de comprensión. Esto se debe a que joinitera dos veces sobre el argumento y, por lo tanto, es más rápido proporcionar una lista lista para usar en lugar de un generador.
Bhargav Rao
1
@BhargavRao, ¿por qué str.joinnecesitaría repetir dos veces el argumento? Acabo de comprobarlo, no lo hace. Aunque para secuencias pequeñas la comprensión de la lista es más rápida.
warvariuc
12

¿Por qué complicas tu vida con uniones y bucles cuando la solución es simple y segura?

Solo haz esto:

string = "the brown fox"
string[0].upper()+string[1:]
Brad Larson
fuente
2
Porque puede haber varias palabras.
Arnaud
1
Sí, pero a menudo solo quiero poner en mayúscula la primera letra. Esta es una manera de hacer eso.
Deleet
1
¿No lo usarías entonces "the brown fox".capitalize()?
luckydonald
2
@luckydonald Porque tal vez no quiero convertir 'this is John'en 'This is john'.
janek37
No es una mejor manera de hacer esto simplemente string.capitalize()(esencialmente haciéndose eco de @luckydonald)
Hassan Baig
10

Si str.title () no funciona para usted, haga las mayúsculas usted mismo.

  1. Divide la cadena en una lista de palabras
  2. Poner en mayúscula la primera letra de cada palabra
  3. Une las palabras en una sola cadena

Un trazador de líneas:

>>> ' '.join([s[0].upper() + s[1:] for s in "they're bill's friends from the UK".split(' ')])
"They're Bill's Friends From The UK"

Claro ejemplo:

input = "they're bill's friends from the UK"
words = input.split(' ')
capitalized_words = []
for word in words:
    title_case_word = word[0].upper() + word[1:]
    capitalized_words.append(title_case_word)
output = ' '.join(capitalized_words)
jibberia
fuente
1
Un punto de interés con esta solución es que pierde cualquier espacio en blanco especial. Puede no ser importante según el contexto.
mklauber
8

Si solo quieres la primera letra:

>>> 'hello world'.capitalize()
'Hello world'

Pero para capitalizar cada palabra:

>>> 'hello world'.title()
'Hello World'
Zahran
fuente
Cuidado porque 'hello New York'.capitalize()es'Hello new york'
user2314737
5

Una cadena vacía generará un error si accede a [1:], por lo tanto, usaría:

def my_uppercase(title):
    if not title:
       return ''
    return title[0].upper() + title[1:]

en mayúscula solo la primera letra.

Wim Feijen
fuente
¿No es eso para lo que str.capitalizesirve?
Eugene Pakhomov el
44
@Eugene, sí, pero desafortunadamente, escribe con mayúscula en minúsculas todas las demás letras que podrían no ser deseables. : /
Wim Feijen
return title[:1].upper() + title[1:]También se encargará de eso problema, ya que cortar la cadena vacía como eso daría a 2 cadenas vacías, se unieron hacer una cadena vacía que se devuelve
aljgom
3

Como Mark señaló, debes usar .title():

"MyAwesomeString".title()

Sin embargo, si desea poner la primera letra en mayúscula dentro de una plantilla de django , puede usar esto:

{{ "MyAwesomeString"|title }}

o usando una variable:

{{ myvar|title }}
Chuckfinley
fuente
3

El método sugerido str.title () no funciona en todos los casos. Por ejemplo:

string = "a b 3c"
string.title()
> "A B 3C"

en lugar de "A B 3c".

Creo que es mejor hacer algo como esto:

def capitalize_words(string):
    words = string.split(" ") # just change the split(" ") method
    return ' '.join([word.capitalize() for word in words])

capitalize_words(string)
>'A B 3c'
Sören
fuente
1
sin embargo, puede surgir un error si el número de espacios que los separan no es 1. Para referencia: problema de hackerrank
Divakar Rajesh
3

Aunque todas las respuestas ya son satisfactorias, trataré de cubrir los 2 casos adicionales junto con todos los casos anteriores.

si los espacios no son uniformes y quieres mantener el mismo

string = hello    world i  am    here.

si todas las cadenas no comienzan desde alfabetos

string = 1 w 2 r 3g

Aquí puedes usar esto

def solve(s):
    a = s.split(' ')
    for i in range(len(a)):
        a[i]= a[i].capitalize()
    return ' '.join(a)

esto te dará

output = Hello    World I  Am    Here
output = 1 W 2 R 3g

Espero que esto no sea redundante.

Amit Gupta
fuente
2
Gracias por destacar el caso de los espacios no uniformes. Algunas respuestas anteriores usan s.split () en lugar de s.split (''). ¡Es importante tener en cuenta que para espacios no uniformes, usar s.split ('') asegurará que se mantengan los espacios no uniformes! Gracias de nuevo
manpikin
Esto funciona perfectamente para palabras con espacios desiguales o palabras que comienzan con algún dígito. Gracias :)
Amresh Giri
2

Para capitalizar palabras ...

str = "this is string example....  wow!!!";
print "str.title() : ", str.title();

@ Gary02127 comentario, debajo del título del trabajo de solución con apóstrofe

import re

def titlecase(s):
    return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", lambda mo: mo.group(0)[0].upper() + mo.group(0)[1:].lower(), s)

text = "He's an engineer, isn't he? SnippetBucket.com "
print(titlecase(text))
Tanque Tejas
fuente
Usar la función existente proporciona una ejecución rápida en python.
Tejas Tank
No me gusta mucho title (), ya que no maneja apóstrofes. "No puedo decir" .title () da "No puedo decir"
Gary02127
@ Gary02127 Tenía una respuesta actualizada, por favor, eche un vistazo, funcionó perfectamente con el dominio de su problema también
Tejas Tank
1

No pase por alto la preservación del espacio en blanco. Si desea procesar 'fred flinstone'y obtiene en 'Fred Flinstone'lugar de 'Fred Flinstone', ha corrompido su espacio en blanco. Algunas de las soluciones anteriores perderán espacio en blanco. Aquí hay una solución que es buena para Python 2 y 3 y conserva el espacio en blanco.

def propercase(s):
    return ''.join(map(''.capitalize, re.split(r'(\s+)', s)))
Gary02127
fuente
0

Una función rápida funcionó para Python 3

Python 3.6.9 (default, Nov  7 2019, 10:44:02) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> capitalizeFirtChar = lambda s: s[:1].upper() + s[1:]
>>> print(capitalizeFirtChar('помните своих Предковъ. Сражайся за Правду и Справедливость!'))
Помните своих Предковъ. Сражайся за Правду и Справедливость!
>>> print(capitalizeFirtChar('хай живе вільна Україна! Хай живе Любовь поміж нас.'))
Хай живе вільна Україна! Хай живе Любовь поміж нас.
>>> print(capitalizeFirtChar('faith and Labour make Dreams come true.'))
Faith and Labour make Dreams come true.
PADYMKO
fuente
0

Capitalizar cadena con espacios no uniformes

Bueno, entiendo que esta es una vieja pregunta y probablemente las respuestas casi se hayan agotado, pero me gustaría agregar al punto de espacios no uniformes de @Amit Gupta. De la pregunta original, nos gustaría capitalizar cada palabra en la cadena s = 'the brown fox'. ¿Qué pasa si la cadena estaba s = 'the brown fox'con espacios no uniformes?

def solve(s):
    # if you want to maintain the spaces in the string, s = 'the brown      fox'
    # use s.split(' ') instead of s.split(). 
    # s.split() returns ['the', 'brown', 'fox']
    # while s.split(' ') returns ['the', 'brown', '', '', '', '', '', 'fox']
    capitalized_word_list = [word.capitalize() for word in s.split(' ')]
    return ' '.join(capitalized_word_list)
manpikin
fuente
.. su código no puede compensar las pestañas si no son espacios en blanco entre marrón y zorro ;-)
ZF007
-1

** En caso de que quiera reducir el tamaño **

 #Assuming you are opening a new file   
 with open(input_file) as file:
     lines = [x for x in reader(file) if x]
 #for loop to parse the file by line
 for line in lines:
           name = [x.strip().lower() for x in line if x]
           print(name) #check the result
Fouad Djebbar
fuente
-2

Realmente me gusta esta respuesta:

Versión lista para copiar y pegar de @jibberia anwser:

def capitalize(line):
    return ' '.join([s[0].upper() + s[1:] for s in line.split(' ')])

Pero algunas de las líneas que estaba enviando separaron algunos caracteres en blanco '' que causaron errores al intentar hacer s [1:]. Probablemente haya una mejor manera de hacer esto, pero tuve que agregar un if len (s)> 0, como en

return ' '.join([s[0].upper() + s[1:] for s in line.split(' ') if len(s)>0])
usuario1475777
fuente
2
Esto es demasiado complicado, ¿incluso vas a verificar la longitud? ineficiente.