Як перетворити рядок у регістр заголовка в Python?


96

Приклад:

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

Чи існує бібліотека або стандартний спосіб виконання цього завдання?


16
Це не "CamelCase", це "Великі літери"; що ти хочеш?
Ендрю Маршалл

13
camelCase isLike this.
Джонатан М

5
Ваші приклади використовують PascalCase.
David Betz

Відповіді:


218

Чому б не використовувати title прямо з документів:

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

Якщо ви дійсно хотіли PascalCase, ви можете використовувати це:

>>> ''.join(x for x in 'make IT pascal CaSe'.title() if not x.isspace())
'MakeItPascalCase'

5
Я думаю, що "r" у "Вони" мають бути малими. І «s» у «Біллі», безумовно, мають бути малими.
Даніель Фішер

3
@Daniel - Ця проблема зазначається в документах до title: "Алгоритм використовує просте незалежне від мови визначення слова як групи послідовних букв. Визначення працює у багатьох контекстах, але це означає, що апострофи в скороченнях і присвійних знаках утворюють межі слів, що може бути не бажаним результатом ". Одним із можливих рішень було б використовувати відповідь Лоуренса з регулярним виразом, r"['\w]+"щоб апострофи не закінчували збіг (за потреби можна додати додаткові знаки пунктуації).
Ендрю Кларк

18
Для запису, більш акуратний спосіб зробити останній приклад CamelCase - це як 'make IT camel CaSe'.title().replace(' ', '').
Генрі Гомерсолл,

15
Якщо хтось ще відчуває, що він на божевільних таблетках - це PascalCase, а не camelCase.
Роб

4
Хороший код, але camelCase починається не з ВЕЛИКОГО. Спробуйте це: def toCamel(s): ret = ''.join(x for x in s.title() if not x.isspace()) return ret[0].lower() + ret[1:] Використання:toCamel("WRITE this in camelcase") 'writeThisInCamelcase'
Рон Каліан

21

Це завжди починалося б з малих літер, а також позбавляло б не буквено-цифрових символів:

def camelCase(st):
    output = ''.join(x for x in st.title() if x.isalnum())
    return output[0].lower() + output[1:]

8
def capitalizeWords(s):
  return re.sub(r'\w+', lambda m:m.group(0).capitalize(), s)

re.subможе взяти функцію для "заміни" (а не просто рядок, який, як видається, знайомий більшості людей). Ця функція repl буде викликана з re.Matchоб'єктом для кожного збігу шаблону, а результат (який повинен бути рядком) буде використаний як заміна цього збігу.

Довша версія того самого:

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

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

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

Це попередньо компілює шаблон (зазвичай вважається хорошою формою) і використовує іменовану функцію замість лямбда.


цей досить акуратний, я намагаюся розібратися з лямбда-функціями, дякую за допомогу
daydreamer

1
@JohnMachin Я щойно запитав, бо, на мою думку, додавши якесь пояснення, ваша відповідь стане повнішою та кращою.
NN

@Laurence Gonsalves, що тут робить лямбда?
Сіон

що тут робить лямбда? з чого я можу розшифрувати і з вашого пояснення. це те, що я зрозумів. коли ви використовуєте функцію в re.sub, кожна matchбуде передана функції? а оскільки matchesв регулярних виразах є групи. ось чому ця лінія існує lambda m:m.group(0).capitalize()?
Сіон

@Zion так. Коли re.subйому дається виклик (наприклад: функція) як "заміна", він передає об'єкт збігу з цим викликом і розраховує повернути рядок, який він фактично використовує в якості заміни. Якщо вам здається, що лямбди заплутані, «довша версія» робить точно те саме, більш детально.
Лоуренс Гонсалвес,

5

Чому б не написати одного? Щось подібне може задовольнити ваші вимоги:

def FixCase(st):
    return ' '.join(''.join([w[0].upper(), w[1:].lower()]) for w in st.split())

дякую, це допомогло повністю. Шкода, я не думав писати його спочатку
мрійник

5

Примітка: Чому я даю ще одну відповідь? Ця відповідь базується на назві питання та уявленні, що верблюд визначається як: серія слів, які були об'єднані (без пробілів!), Так що кожне з оригінальних слів починається з великої літери (решта - з малої літери) за винятком першого слова серії (яке є повністю малою). Також передбачається, що "всі рядки" відноситься до набору символів ASCII; unicode не працює з цим рішенням).

просто

Враховуючи наведене вище визначення, ця функція

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

, якщо його викликати, це призведе до цього

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

менш простий

Зверніть увагу, що це не вдається, якщо його подарувати вже в’язаній верблюдом струні!

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

ще менш простий

Зверніть увагу, що це не вдається з багатьма рядками Unicode

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

У мене немає рішення для цих випадків (або інших, які можна було б представити з певною творчістю). Отже, як і у всіх речах, пов’язаних із струнами, покрийте власні випадки краю та удачі Unicode!


Як можна визначити, що рядок - це випадок верблюда, не знаючи значення речення? У вашому "менш простому" прикладі "sanfRancisco" - це випадок верблюда, а також "itSnotcaMelcAse".
Патріс Бернассола,

Я думаю, у вашому введенні були апострафи чи інші розділові знаки? Слід зазначити інші невдалі введення. Безумовно, хороший улов. Який внесок ви надали?
Марк

1
Я маю на увазі, що послідовність символів без пробілу повинна розглядатися як одне слово. Ви не можете витягти з нього твір, не знаючи значення речення. Помістіть "sanfRancisco" або "itSnotcaMelcAse" як вхідні дані camello (), і ви побачите, що результат буде однаковим.
Patrice Bernassola

О, я розумію - так, я думаю, ти маєш рацію. Я переоцінюю рішення. Я оновлю його.
Марк

4

Потенційна бібліотека: https://pypi.org/project/stringcase/

Приклад:

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

Хоча сумнівно, чи залишатиме пробіли. (Приклади показують, що він вилучає простір, але є проблема з відстежувачем помилок, зазначаючи, що він залишає їх там.)


Чорт возьми, так. Шукав пакет. Цей пакет також має змійний футляр та інші функції перетворення.
s2t2

1

просто використовуйте .title (), і він перетворить першу літеру кожного слова з великої літери, а решту в малому:

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

1

Я хотів би додати свій невеликий внесок до цього допису:

def to_camelcase(str):
  return ' '.join([t.title() for t in str.split()])

Насправді, str.title () однаковий, і ви економите обчислювальні витрати.
Auros132

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.