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


587
s = 'the brown fox'

... зробіть щось тут ...

s має бути :

'The Brown Fox'

Який найпростіший спосіб це зробити?

Відповіді:


987

.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())
нав'язливої

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 відсутній або None, пробіли символів пробілів замінюються одним пробілом, а провідні та кінцеві пробіли видаляються, інакше sep використовується для розділення та об'єднання слів.


2
Капсулів все ще бракує і не обробляє щось подібне "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()цьому правильно обробляйте їх.
houcros

Добре, але це все-таки псує відмінність "Великобританія"
Jonath P

104

Тільки тому, що така штука для мене цікава, ось ще два рішення.

Розділіть на слова, заздалегідь замініть кожне слово з розділених груп та приєднайтеся. Це змінить пробіл, що розділяє слова, на єдиний пробіл, незалежно від того, яким він був.

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

EDIT: Я не пам'ятаю, про що я думав, коли писав вищезгаданий код, але немає необхідності створювати чіткий список; ми можемо використовувати генераторний вираз, щоб зробити це в ледачому порядку. Тож ось краще рішення:

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()щоб отримати кінцевий результат!


1
+1 для розчину за допомогою скибочок. Мені знадобилося щось, що дозволить писати великі літери, не змінюючи великі літери решти слів (наприклад, Foo стає foo, але FOO стає FOO). Це було ідеально.
TomNysetvold

1
capitalize повертає перший символ з великої літери, а решта з нижнього регістру
Вануань

@ Вануан, ти маєш рацію! Опис рядкового документа змусило мене подумати, що все, що він робив, - це написання великої літери на першому листі, але ви маєте рацію щодо того, що він насправді робить. Я відредагую відповідь. Дякую за голову.
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) )

- Або ви можете використовувати регулярні вирази, з відповіді steveha :

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

+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

Перші способи, зазначені вище, не змінюють літери, які вже були WW1WW1
написані з

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повторюється двічі над аргументом, а значить, швидше надати готовий список, а не генератор.
Bhargav Rao

1
@BhargavRao, чому str.joinпотрібно було б двічі повторити аргумент? Я щойно перевірив - це не так. Хоча для невеликих послідовностей розуміння списку справді швидше.
warvariuc

12

Чому ви ускладнюєте своє життя приєднанням і петлям, коли рішення просте і безпечне ??

Просто зробіть це:

string = "the brown fox"
string[0].upper()+string[1:]

2
Бо може бути кілька слів.
Арно

1
Так, але часто мені хочеться лише з великої літери прописати першу букву. Це спосіб це зробити.
Делете

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)

1
Одним із цікавих моментів цього рішення є те, що ви втрачаєте будь-який спеціальний пробіл. Може не важливо залежно від контексту.
mklauber

8

Якщо ви хочете лише перший лист:

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

Але з великої літери використовувати кожне слово:

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

Обережно, тому що '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
@Eugene, так, але, на жаль, використовуйте великі регістри всіх інших літер, які можуть бути не бажаними. : /
Вім Фейєн

return title[:1].upper() + title[1:]також би піклувався про цю проблему, оскільки нарізання порожнього рядка таким чином дало б 2 порожні рядки, об'єднавшись разом, зробити порожню рядок, яка повертається
aljgom

3

Як зазначав Марк, ви повинні використовувати .title():

"MyAwesomeString".title()

Однак, якщо ви хочете зробити пропис першої літери всередині шаблону django , ви можете скористатися цим:

{{ "MyAwesomeString"|title }}

або за допомогою змінної:

{{ myvar|title }}

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. Для довідки: проблема з
хакерранком

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 ('') забезпечить збереження нерівномірних пробілів! Ще раз
дякую

Це чудово працює для слів з нерівними пробілами або слів, що починаються з якоїсь цифри. Дякую :)
Amresh Giri

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

Використання існуючої функції дає швидке виконання в python.
Tejas Tank

Я не дуже люблю заголовок (), оскільки він не обробляє апострофи. "Я не можу сказати" .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)))

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.

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)

.. ваш код не зможе компенсувати вкладки, якщо його не пробіли між коричневим та лисом ;-)
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:]. Можливо, є кращий спосіб зробити це, але мені довелося додати в, якщо len (s)> 0, як у

return ' '.join([s[0].upper() + s[1:] for s in line.split(' ') if len(s)>0])

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