Jak przekonwertować ciąg na wielkość liter w Pythonie?

97

Przykład:

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

Czy istnieje biblioteka lub standardowy sposób wykonania tego zadania?

marzyciel
źródło
16
To nie jest „CamelCase”, to jest „Capitalize”; Które chcesz?
Andrew Marshall
13
camelCase jest jak to.
Jonathan M
5
Twoje przykłady wykorzystują PascalCase.
David Betz,

Odpowiedzi:

219

Dlaczego nie skorzystać bezpośrednio titlez dokumentacji:

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

Jeśli naprawdę chciałeś PascalCase, możesz użyć tego:

>>> ''.join(x for x in 'make IT pascal CaSe'.title() if not x.isspace())
'MakeItPascalCase'
Facundo Casco
źródło
5
Myślę, że „r” w słowie „Oni” powinno być małe. A „s” w „Bill's” zdecydowanie musi być małymi literami.
Daniel Fischer,
3
@Daniel - Ta kwestia jest odnotowana w dokumentach dla title: „Algorytm używa prostej, niezależnej od języka definicji słowa jako grup następujących po sobie liter. Definicja działa w wielu kontekstach, ale oznacza, że ​​apostrofy w skrótach i dzierżawcze tworzą granice słów, co może nie być pożądanym rezultatem ”. Jednym z możliwych rozwiązań byłoby użycie odpowiedzi Laurence'a z wyrażeniem regularnym, r"['\w]+"aby apostrofy nie kończyły dopasowania (w razie potrzeby można było dodać dodatkowe znaki interpunkcyjne).
Andrew Clark
18
Dla przypomnienia, bardziej schludnym sposobem wykonania ostatniego przykładu CamelCase jest użycie pliku 'make IT camel CaSe'.title().replace(' ', '').
Henry Gomersall,
15
Jeśli ktoś czuje, że bierze szalone pigułki - to PascalCase, a nie camelCase.
Rob
4
Niezły kod, ale camelCase nie zaczyna się od WIELKIEGO. Spróbuj tego: def toCamel(s): ret = ''.join(x for x in s.title() if not x.isspace()) return ret[0].lower() + ret[1:] Sposób użycia:toCamel("WRITE this in camelcase") 'writeThisInCamelcase'
Ron Kalian
22

Ten zawsze zaczynałby się od małych liter, a także usuwał znaki inne niż alfanumeryczne:

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

re.submoże przyjąć funkcję do „zamiany” (zamiast zwykłego ciągu znaków, co wydaje się być znane większości ludzi). Ta funkcja repl zostanie wywołana z re.Matchobiektem dla każdego dopasowania wzorca, a wynik (który powinien być łańcuchem znaków) zostanie użyty jako zamiennik dla tego dopasowania.

Dłuższa wersja tego samego:

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

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

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

To wstępnie kompiluje wzorzec (ogólnie uważany za dobrą formę) i używa nazwanej funkcji zamiast lambda.

Laurence Gonsalves
źródło
ten jest całkiem fajny, próbuję ogarnąć funkcje lambda, dziękuję za pomoc
daydreamer
1
@JohnMachin Właśnie zapytałem, ponieważ pomyślałem, że dodanie wyjaśnienia sprawi, że Twoja odpowiedź będzie pełniejsza i lepsza.
NN
@Laurence Gonsalves, co tu robi lambda?
Zion
co tu robi lambda? z tego, co mogę rozszyfrować i od Ciebie wyjaśnienia. to właśnie zrozumiałem. kiedy używasz funkcji w re.sub, każda z nich matchzostanie przekazana do funkcji? a ponieważ matchesw wyrażeniach regularnych mają grupy. dlatego istnieje ta linia lambda m:m.group(0).capitalize()?
Zion
@Zion yes. Kiedy re.subjako „zamiennik” otrzyma wywoływalną funkcję (np. Funkcję), przekazuje obiekt dopasowania do tego wywoływalnego i oczekuje, że odzyska łańcuch, którego faktycznie używa jako zamiennika. Jeśli uznasz lambdy za mylące, „dłuższa wersja” robi dokładnie to samo, w bardziej szczegółowy sposób.
Laurence Gonsalves
5

Dlaczego by nie napisać? Coś takiego może spełnić Twoje wymagania:

def FixCase(st):
    return ' '.join(''.join([w[0].upper(), w[1:].lower()]) for w in st.split())
wiele interfejsów
źródło
dzięki, to pomogło całkowicie. Mój zły, nie pomyślałem, żebym napisał jeden na pierwszym miejscu
marzyciel
5

Uwaga: dlaczego udzielam jeszcze innej odpowiedzi? Ta odpowiedź opiera się na tytule pytania i założeniu, że wielkie litery definiuje się jako: serię słów, które zostały połączone (bez spacji!) W taki sposób, że każde z oryginalnych słów zaczyna się wielką literą (reszta jest małą) z wyjątkiem pierwszego słowa z serii (które jest całkowicie małe). Zakłada się również, że „wszystkie łańcuchy” odnoszą się do zestawu znaków ASCII; Unicode nie będzie działać z tym rozwiązaniem).

prosty

Biorąc pod uwagę powyższą definicję, ta funkcja

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

, gdy zostanie wywołany, spowoduje to w ten sposób

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

mniej proste

Zwróć uwagę, że nie udaje się, gdy jest przedstawiony ze sznurkiem w wielbłądzie!

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

jeszcze mniej proste

Zauważ, że kończy się niepowodzeniem z wieloma ciągami znaków Unicode

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

Nie mam rozwiązania dla tych przypadków (lub innych, które można by wprowadzić przy odrobinie kreatywności). Tak więc, podobnie jak we wszystkich rzeczach, które mają związek ze strunami, zakryj własne skrajne przypadki i powodzenia w unicode!

Marc
źródło
Jak możesz ustalić, że ciąg znaków to przypadek Camel, nie znając znaczenia zdania? W twoim „mniej prostym” przykładzie „sanfRancisco” to zarówno obudowa Camel, jak i „itSnotcaMelcAse”.
Patrice Bernassola
Zgaduję, że Twój wpis zawierał apostyk lub inną interpunkcję? Powinienem zwrócić uwagę na inne błędne dane wejściowe. Zdecydowanie dobry połów. Jaki był Twój wkład?
Marc,
1
Chodzi mi o to, że ciąg znaków bez spacji należy traktować jako 1 słowo. Nie możesz wydobyć z niego pracy bez znajomości znaczenia zdania. Umieść "sanfRancisco" lub "itSnotcaMelcAse" jako wejście funkcji camello (), a zobaczysz, że wynik będzie taki sam.
Patrice Bernassola
Och, rozumiem - tak, myślę, że masz rację. Przekonałem rozwiązanie. Zaktualizuję to.
Marc
4

Potencjalna biblioteka: https://pypi.org/project/stringcase/

Przykład:

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

Chociaż wątpliwe jest, czy pozostawi spacje. (Przykłady pokazują, że usuwa spację, ale istnieje problem z trackerem błędów, który zauważa, że ​​pozostawia je).

Lol
źródło
Pewnie, ze tak. Szukałem paczki. Ten pakiet ma również futerał na wąż i inne funkcje konwersji.
s2t2
1

po prostu użyj .title (), a skonwertuje pierwszą literę każdego słowa z wielkiej litery, resztę na małe:

>>> a='mohs shahid ss'
>>> a.title()
'Mohs Shahid Ss'
>>> a='TRUE'
>>> b=a.title()
>>> b
'True'
>>> eval(b)
True
Mohammad Shahid Siddiqui
źródło
1

Chciałbym dodać swój mały wkład do tego postu:

def to_camelcase(str):
  return ' '.join([t.title() for t in str.split()])
Evhz
źródło
W rzeczywistości str.title () działa tak samo, a Ty oszczędzasz na kosztach obliczeniowych.
Auros132
1
def camelCase(st):
    s = st.title()
    d = "".join(s.split())
    d = d.replace(d[0],d[0].lower())
    return d
Aishwarya Skandamani
źródło