Как преобразовать строку в регистр заголовка в Python?

97

Пример:

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

Есть библиотека или стандартный способ выполнить эту задачу?

мечтатель
источник
16
Это не «CamelCase», это «Capitalize»; Какой ты хочешь?
Эндрю Маршалл
13
camelCase вот такой.
Jonathan M
5
В ваших примерах используется PascalCase.
Дэвид Бец

Ответы:

219

Почему бы не использовать titleRight from the docs:

>>> "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" в слове "They're" должно быть в нижнем регистре. И "s" в слове "Bill'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'
Рон Калиан
22

Это всегда будет начинаться с нижнего регистра, а также удалять не буквенно-цифровые символы:

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, что здесь делает лямбда?
Zion
что здесь делает лямбда? от чего я могу расшифровать и от вас объяснение. вот что я понял. когда вы используете функцию в 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())
несколько интерфейсов
источник
спасибо, что помогло полностью. Мой плохой, я не подумал написать его на первом месте
daydreamer
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

У меня нет решения для этих случаев (или других, которые можно было бы представить с некоторым творчеством). Итак, как и во всем, что связано со строками, примите во внимание свои собственные крайние случаи и удачи с юникодом!

Марк
источник
Как вы можете определить, что строка является регистром Camel, не зная значения предложения? В вашем «менее простом» примере «sanfRancisco» - это случай Camel, а также «itSnotcaMelcAse».
Патрис Бернассола
Я предполагаю, что в вашем вводе были апострафы или другие знаки препинания? Я должен отметить другой неудачный ввод. Определенно хороший улов. Какой вклад вы внесли?
Marc
1
Я имею в виду, что последовательность символов без пробела следует рассматривать как 1 слово. Вы не можете извлечь из него работу, не зная смысла предложения. Введите «sanfRancisco» или «itSnotcaMelcAse» в качестве входных данных для camello (), и вы увидите, что результат будет таким же.
Патрис Бернассола
О, я понимаю - да, я думаю, ты прав. Я переоснащаю решение. Я обновлю его.
Marc
4

Возможная библиотека: https://pypi.org/project/stringcase/

Пример:

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

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

Лол
источник
Да черт возьми. Искал посылку. В этом пакете есть snakecase и другие функции преобразования.
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()])
Evhz
источник
На самом деле str.title () то же самое, и вы экономите вычислительные затраты.
Auros132
1
def camelCase(st):
    s = st.title()
    d = "".join(s.split())
    d = d.replace(d[0],d[0].lower())
    return d
Айшвария Скандамани
источник