Как сделать заглавной первую букву каждого слова в строке?

589
s = 'the brown fox'

... сделать что-то здесь ...

s должно быть :

'The Brown Fox'

Какой самый простой способ сделать это?

TIMEX
источник

Ответы:

991

.title()Метод строки (ASCII или UNICODE штрафа) делает это:

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

Однако обратите внимание на строки со встроенными апострофами, как отмечено в документации.

Алгоритм использует простое независимое от языка определение слова как группы последовательных букв. Определение работает во многих контекстах, но оно означает, что апострофы в сокращениях и притяжениях образуют границы слов, что может не соответствовать желаемому результату:

>>> "they're bill's friends from the UK".title()
"They'Re Bill'S Friends From The Uk"
Марк Рушаков
источник
56
Я избегаю притяжательных проблем с чем-то вроде" ".join(w.capitalize() for w in s.split())
mehtunguh
3
это не безопасно для большинства строк, потому что каждое слово, даже собственническое, записывается в верхнем регистре.
10
Существует проблема с string.title (). Когда вы используете, например, "e g 3b"желаемый результат будет "E G 3b". Однако "e g 3b".title()возвращается "E G 3B".
Сёрен
7
Имейте в виду, что это также приведет к этому:In [2]: 'tEst'.title() Out[2]: 'Test'
Йонас Либбрехт
4
Отличный ответ, и комментарии подчеркивают, что в python не все ведет себя так, как вам нужно, но всегда есть удобные способы сделать это. Наиболее удобный способ - часто импортировать специализированную библиотеку, такую ​​как python-titlecase
Aaron3468
189

.title()Метод не может хорошо работать,

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

Попробуй string.capwords()метод,

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

Из документации по питону на заглавных словах :

Разбейте аргумент на слова с помощью str.split (), используйте каждое слово с заглавной буквы с помощью str.capitalize () и объедините слова с заглавными буквами с помощью str.join (). Если необязательный второй аргумент sep отсутствует или отсутствует, последовательности пробельных символов заменяются одним пробелом, а начальные и конечные пробелы удаляются, в противном случае sep используется для разделения и объединения слов.

Чен Хоуу
источник
2
Capwords по-прежнему отсутствует и не обрабатывает что-то вроде "There once was a string with an 'that had words right after it and then closed'". В этом примере все миры, за исключением thatзаглавных, как и ожидалось. Результаты были"There Once Was A String With An 'that Had Words Right After It And Then Closed'"
devonbleibtrey
Тем не менее, это работает лучше, чем title()в обычных ситуациях. В моей ситуации title()возвращает неверный вывод для имен с акцентом или диерезисом, при этом capwords()обрабатывается правильно.
Укрос
1
Хорошо, но это все еще портит различие "Великобритания / Великобритания"
Джонат П
1
@ Чен Хоуу, Великобритания / Великобритания - прекрасный контрпример. Как предотвратить использование Python прописными буквами в нижнем регистре аналогичным способом?
h0r53
105

Просто потому, что мне это нравится, вот еще два решения.

Разделите на слова, начальное заглавие каждого слова из разделенных групп и воссоединиться. Это изменит пробел, разделяющий слова на один пробел, независимо от того, что это было.

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

РЕДАКТИРОВАТЬ: я не помню, о чем я думал, когда писал вышеупомянутый код, но нет необходимости создавать явный список; мы можем использовать выражение генератора, чтобы сделать это ленивым способом. Итак, вот лучшее решение:

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

Используйте регулярное выражение для сопоставления начала строки или пробела, разделяющего слова, плюс один непробельный символ; используйте круглые скобки, чтобы пометить «группы соответствия». Напишите функцию, которая принимает объект сопоставления и возвращает группу совпадений с пробелами без изменений и группу сопоставления непробельных символов в верхнем регистре. Затем используйте re.sub()для замены шаблонов. У этого нет проблем пунктуации первого решения, и при этом это не переделывает пробел как мое первое решение. Этот дает лучший результат.

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"

Я рад, что исследовал этот ответ. Я понятия не имел, что re.sub()может взять на себя функцию! Вы можете сделать нетривиальную обработку внутри, re.sub()чтобы получить конечный результат!

steveha
источник
1
+1 за решение с использованием ломтиков. Мне нужно что-то, что могло бы использовать заглавные буквы без изменения заглавных букв остальных слов (например, Foo становится foo, но FOO становится fOO). Это было прекрасно.
TomNysetvold
1
капитализация возвращает свой первый символ с заглавной буквы, а остальные в нижнем регистре
Вануан
@ Вануан, ты прав! Описание строки документа заставило меня подумать, что все, что он сделал, это заглавная буква первой буквы, но вы правы в том, что на самом деле делает. Я отредактирую ответ. Спасибо за хедз-ап.
Steveha
Похоже, это то string.capwords, что делает, согласно документации в ответе Чэнь Хоуу.
Адриан
1
Что-то, что нужно отметить в ответе выше, вместо использования s.split (), я думаю, что лучше использовать s.split (''). Это потому, что если в строке есть несколько двойных пробелов, и вы хотите сохранить эти двойные пробелы при соединении, s.plit ('') поможет вам сохранить пробелы, а s.split () не будет
manpikin
21

Вот краткое изложение различных способов сделать это, они будут работать для всех этих входных данных:

""           => ""       
"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"     

- Самое простое решение - разделить предложение на слова и использовать заглавную букву, а затем соединить его вместе:

# 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(' ')) 

- Если вы не хотите сначала разбивать входную строку на слова и использовать необычные генераторы:

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

- Или без импорта itertools:

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

- Или вы можете использовать регулярные выражения из ответа Стивехи :

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

Теперь, это некоторые другие ответы, которые были опубликованы, и входные данные, для которых они не работают должным образом, если мы используем определение слова, являющегося началом предложения или чего-либо после пробела:

  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"      

использование '' для разбиения исправит второй вывод, но capwords () все равно не будет работать для первого

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

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

Будьте осторожны с несколькими пробелами

  return ' '.join(w[0].upper() + w[1:] for w in s.split())
# Undesired outputs:
"foo    bar" => "Foo Bar"                 
aljgom
источник
+1 для всестороннего резюме. Я ищу способ использовать только заглавные буквы после числа (не каждое слово). Не могли бы вы сделать дополнение к своему ответу, который демонстрирует это? Например, lower 123 upperдолжно возвращаться lower 123 Upper, где upperзаглавная, как следует за числом. Я знаю, что это выходит за рамки вопроса ОП, но является хорошим дополнением к вашему уже обширному ответу. Заранее спасибо.
ProGrammer
В этом случае вы можете изменить некоторые из вышеперечисленных методов в соответствии с вашими потребностями. Однако я бы не стал добавлять его как часть ответа, поскольку это не то, что ищут большинство людей. Я бы использовал для этого версию регулярного выражения и использовал "([0-9]+)(\s+.)"вместо "(^|\s)(\S)"(совпадение с одним или несколькими числами, после которых следуют один или несколько пробелов и любой символ после), или "([0-9]+)(\s*.)"если вы хотите использовать символ с большой буквы после пробела «ноль или более» после число
aljgom
Я обязательно изучу это, что заставило меня задуматься о другом особом случае: как бы вы изменили приведенные выше фрагменты, чтобы они взяли строку, например, WW1 - the great warи вывели WW1 - The Great Warвместо Ww1 .... Видите проблему с сокращениями? Хотели бы вы добавить что-то, что демонстрирует этот случай? Я долго размышлял об этом и не могу придумать, как это сделать.
ProGrammer
Первые способы, описанные выше, не изменяют буквы, которые уже были прописными во входной строке, поэтому WW1выводятся какWW1
aljgom
15

Готовая к копированию и вставке версия @jibberia anwser:

def capitalize(line):
    return ' '.join(s[:1].upper() + s[1:] for s in line.split(' '))
Константин Спирин
источник
2
Нет необходимости строить список. str.joinпринимает генераторы.
warvariuc
@warvariuc, как бы вы изменили этот код, чтобы использовать генераторы?
Константин Спирин
1
Просто снимите квадратные скобки, как это сделано здесь
warvariuc
1
Хотя @warvariuc идеально подходит для упоминания того, что joinпринимает gen exps, в str.joinчастности, обычно предпочтительнее использовать понимание списка. Это связано с тем, joinчто аргумент проходит дважды по аргументу, и, следовательно, быстрее создать готовый список, а не генератор.
Бхаргав Рао
1
@BhargavRao, почему str.joinнужно дважды повторять аргумент? Я только что проверил - это не так. Хотя для небольших последовательностей понимание списка действительно быстрее.
warvariuc
12

Почему вы усложняете свою жизнь соединениями и циклами, когда решение простое и безопасное?

Просто сделай это:

string = "the brown fox"
string[0].upper()+string[1:]
Брэд Ларсон
источник
2
Потому что может быть несколько слов.
Арно
1
Да, но часто я хочу использовать только первую букву. Это способ сделать это.
Deleet
1
Не могли бы вы тогда просто использовать "the brown fox".capitalize()?
luckydonald
2
@luckydonald Потому что, может быть, я не хочу превращаться 'this is John'в 'This is john'.
janek37
Это не лучший способ сделать это просто string.capitalize()(по сути, повторяя @luckydonald)
Хасан
10

Если str.title () не работает для вас, сделайте капитализацию самостоятельно.

  1. Разбить строку на список слов
  2. Прописать первую букву каждого слова
  3. Объедините слова в одну строку

Один лайнер:

>>> ' '.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"

Наглядный пример:

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
источник
1
Интересным моментом этого решения является то, что вы теряете любые специальные пробелы. Может не быть важным в зависимости от контекста.
mklauber
8

Если только вы хотите первую букву:

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

Но, чтобы извлечь выгоду из каждого слова:

>>> 'hello world'.title()
'Hello World'
Zahran
источник
Тщательное , потому что 'hello New York'.capitalize()это'Hello new york'
user2314737
5

Пустая строка вызовет ошибку, если вы получите доступ к [1:], поэтому я бы использовал:

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

в верхнем регистре только первая буква.

Вим Фейен
источник
Разве это не для чего str.capitalize?
Евгений Пахомов
4
@ Евгений, да, но, к сожалению, строчные буквы в верхнем регистре - все остальные буквы, которые могут быть нежелательны. : /
Вим Фейен
return title[:1].upper() + title[1:]также позаботился бы об этой проблеме, так как разрезание пустой строки, как это, дало бы 2 пустые строки, соединенные вместе, чтобы создать пустую строку, которая возвращается
aljgom
3

Как отметил Марк, вы должны использовать .title():

"MyAwesomeString".title()

Однако, если вы хотите сделать первую букву заглавной в шаблоне django , вы можете использовать это:

{{ "MyAwesomeString"|title }}

или используя переменную:

{{ myvar|title }}
chuckfinley
источник
3

Предложенный метод str.title () работает не во всех случаях. Например:

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

вместо "A B 3c".

Я думаю, что лучше сделать что-то вроде этого:

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'
Сёрен
источник
1
однако ошибка может возникнуть, если число пробелов, разделяющих их, не равно 1. Для справки: проблема с хакерранком
Divakar Rajesh
3

Хотя все ответы уже удовлетворительные, но я постараюсь охватить 2 дополнительных случая вместе со всем предыдущим.

если пространства не одинаковы, и вы хотите сохранить то же самое

string = hello    world i  am    here.

если все строки не начинаются с алфавитов

string = 1 w 2 r 3g

Здесь вы можете использовать это

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

это даст вам

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

Я надеюсь, что это не избыточно.

Амит Гупта
источник
2
Спасибо за выделение случая неравномерных пробелов. Некоторые ответы выше используют s.split () вместо s.split (''). Важно отметить, что для неоднородных пробелов использование s.split ('') обеспечит сохранение неоднородных пробелов!
Еще
Это прекрасно работает для слов с неровными пробелами или слов, начинающихся с некоторой цифры. Спасибо :)
Амреш Гири
2

Чтобы использовать слова ...

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

@ Gary02127 комментарий, ниже название работы решения с апострофом

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))
Tejas Tank
источник
Использование существующей функции дает быстрое выполнение в python.
Tejas Tank
Я не очень люблю title (), так как он не обрабатывает апострофы. «Я не могу сказать» .title () дает «Я не могу сказать»
Gary02127
@ Gary02127 Я получил обновленный ответ, пожалуйста, посмотрите, он отлично работал и с вашей проблемной областью
Tejas Tank
1

Не забывайте о сохранении пустого пространства. Если вы хотите обработать, 'fred flinstone'и вы получите 'Fred Flinstone'вместо 'Fred Flinstone', вы испортили пустое пространство. Некоторые из вышеуказанных решений потеряют пустое пространство. Вот решение, которое хорошо для Python 2 и 3 и сохраняет пустое пространство.

def propercase(s):
    return ''.join(map(''.capitalize, re.split(r'(\s+)', s)))
Gary02127
источник
0

Быстрая функция работала для 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
источник
0

Строка с заглавными буквами с неравномерными пробелами

Ну, я понимаю, что это старый вопрос, и, возможно, ответы на него, возможно, были почти исчерпаны, но я хотел бы добавить к точке @Amit Gupta неравномерных пространств. Исходя из исходного вопроса, мы хотели бы использовать каждое слово в строке с большой буквы s = 'the brown fox'. Что делать, если строка была s = 'the brown fox'с неоднородными пробелами.

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
источник
.. ваш код не может компенсировать вкладки, если между пробелом и лисой нет пробелов ;-)
ZF007
-1

** В случае, если вы хотите уменьшить **

 #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
Фуад Джеббар
источник
-2

Мне очень нравится этот ответ:

Готовая к копированию и вставке версия @jibberia anwser:

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

Но некоторые строки, которые я отправлял, отделяли некоторые пустые символы '', которые вызывали ошибки при попытке сделать s [1:]. Вероятно, есть лучший способ сделать это, но мне пришлось добавить в if len (s)> 0, как в

return ' '.join([s[0].upper() + s[1:] for s in line.split(' ') if len(s)>0])
user1475777
источник
2
Это чересчур сложно, даже если вы проверяете длину ?! неэффективен.