Como converter string para Title Case em Python?

94

Exemplo:

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

Existe uma biblioteca ou maneira padrão de realizar esta tarefa?

sonhador
fonte
16
Isso não é "CamelCase", é "Capitalize"; qual você quer?
Andrew Marshall
13
camelCase é assim.
Jonathan M
5
Seus exemplos usam PascalCase.
David Betz

Respostas:

213

Por que não usar o titleRight from the docs:

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

Se você realmente queria PascalCase, você pode usar isto:

>>> ''.join(x for x in 'make IT pascal CaSe'.title() if not x.isspace())
'MakeItPascalCase'
Facundo Casco
fonte
5
Acho que o 'r' em "Eles" deve ser minúsculo. E o 's' em "Bill's" definitivamente deve ser minúsculo.
Daniel Fischer
3
@Daniel - Esse problema é observado nos documentos para title: "O algoritmo usa uma definição simples independente de linguagem de uma palavra como grupos de letras consecutivas. A definição funciona em muitos contextos, mas significa que apóstrofos em contrações e possessivos formam os limites das palavras, que pode não ser o resultado desejado ". Uma solução possível seria usar a resposta de Laurence com o regex r"['\w]+"para que os apóstrofos não encerrassem uma correspondência (pontuação adicional poderia ser adicionada conforme necessário).
Andrew Clark
18
Para que conste, uma maneira mais limpa de fazer o último exemplo do CamelCase é como 'make IT camel CaSe'.title().replace(' ', '').
Henry Gomersall
15
Se alguém mais sente que está tomando pílulas malucas - este é PascalCase, não camelCase.
Rob
4
Bom código, mas camelCase não começa com MAIÚSCULAS. Experimente: 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
21

Este sempre começaria com letras minúsculas e também removeria os caracteres não alfanuméricos:

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

re.subpode ter uma função para a "substituição" (em vez de apenas uma string, que é o uso com o qual a maioria das pessoas parece estar familiarizada). Esta função repl será chamada com um re.Matchobjeto para cada correspondência do padrão, e o resultado (que deve ser uma string) será usado como um substituto para aquela correspondência.

Uma versão mais longa da mesma coisa:

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

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

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

Isso pré-compila o padrão (geralmente considerado uma boa forma) e usa uma função nomeada em vez de um lambda.

Laurence Gonsalves
fonte
este é bem legal, estou tentando entender as funções lambda, obrigado por ajudar
sonhador
1
@JohnMachin Acabei de perguntar porque pensei que adicionar alguma explicação tornaria sua resposta mais completa e melhor.
NN
@Laurence Gonsalves, o que lambda está fazendo aqui?
Zion
o que lambda está fazendo aqui? do que posso decifrar e da sua explicação. isso é o que eu entendi. quando você usa uma função em re.sub cada um matchserá passado para a função? e desde que matchesem expressões regulares tem grupos. é por isso que esta linha existe lambda m:m.group(0).capitalize()?
Zion
@Zion sim. Quando re.subrecebe um chamável (por exemplo: uma função) como a "substituição", ele passa o objeto de correspondência para aquele chamável e espera receber de volta uma string que é o que ele realmente usa como substituição. Se você achar lambdas confusos, a "versão mais longa" faz exatamente a mesma coisa de uma forma mais detalhada.
Laurence Gonsalves de
5

Por que não escrever um? Algo assim pode satisfazer seus requisitos:

def FixCase(st):
    return ' '.join(''.join([w[0].upper(), w[1:].lower()]) for w in st.split())
interfaces múltiplas
fonte
obrigado, isso ajudou completamente. Que pena, eu não pensei em escrever um em primeiro lugar
sonhador
5

Observação: por que estou fornecendo mais uma resposta? Essa resposta é baseada no título da pergunta e na noção de que caixa-de-camelo é definida como: uma série de palavras que foram concatenadas (sem espaços!) De forma que cada uma das palavras originais comece com uma letra maiúscula (o resto sendo minúsculo) exceto a primeira palavra da série (que é totalmente minúscula). Além disso, presume-se que "todas as strings" se refere ao conjunto de caracteres ASCII; Unicode não funcionaria com esta solução).

simples

Dada a definição acima, esta função

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))

, quando chamado, resultaria desta maneira

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

menos simples

Observe que ele falha quando apresentado com uma corda já revestida de camelo!

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

ainda menos simples

Observe que ele falha com muitas strings Unicode

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

Não tenho solução para esses casos (ou outros que poderiam ser apresentados com alguma criatividade). Então, como em todas as coisas que têm a ver com cordas, cubra seus próprios casos extremos e boa sorte com Unicode!

Marc
fonte
Como você pode determinar que uma string é camelo sem saber o significado da frase? No seu exemplo "menos simples", "sanfRancisco" é o caso Camel, bem como "itSnotcaMelcAse".
Patrice Bernassola
Estou supondo que sua entrada teve apóstolos ou outra pontuação? Devo observar outra entrada com falha. Definitivamente, um bom partido. Qual foi a entrada que você forneceu?
Marc
1
Quero dizer que uma sequência de caracteres sem espaço deve ser considerada como 1 palavra. Você não pode extrair trabalho dele sem saber o significado da frase. Coloque "sanfRancisco" ou "itSnotcaMelcAse" como entrada de camello () e você verá que a saída será a mesma.
Patrice Bernassola
Oh, entendo - sim, acho que você está certo. Eu super ajustei a solução. Vou atualizá-lo.
Marc
4

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

Exemplo:

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

Embora seja questionável se deixará espaços. (Os exemplos mostram que ele remove espaço, mas há um problema de rastreador de bug observando que ele os deixa.)

Ri muito
fonte
Claro que sim. Estava procurando um pacote. Este pacote também possui snakecase e outras funções de conversão.
s2t2
1

apenas use .title (), e ele converterá a primeira letra de cada palavra em maiúsculo, o restante em minúsculo:

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

Eu gostaria de adicionar minha pequena contribuição a este post:

def to_camelcase(str):
  return ' '.join([t.title() for t in str.split()])
Evhz
fonte
Na verdade, str.title () é o mesmo e você está economizando custos computacionais.
Auros132
1
def camelCase(st):
    s = st.title()
    d = "".join(s.split())
    d = d.replace(d[0],d[0].lower())
    return d
Aishwarya Skandamani
fonte