Как сделать заглавной первую букву каждого слова в строке (Python)? - PullRequest
495 голосов
/ 11 октября 2009
s = 'the brown fox'

... сделайте что-нибудь здесь ...

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

'The Brown Fox'

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

Ответы [ 15 ]

826 голосов
/ 11 октября 2009

Метод строки .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"
170 голосов
/ 09 сентября 2012

Метод .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 используется для разделения и объединения слов.

92 голосов
/ 11 октября 2009

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

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

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(), чтобы получить конечный результат!

14 голосов
/ 04 апреля 2012

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

def capitalize(line):
    return ' '.join(s[:1].upper() + s[1:] for s in line.split(' '))
13 голосов
/ 28 февраля 2017

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

""           => ""       
"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"                 
11 голосов
/ 29 августа 2014

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

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

string = "the brown fox"
string[0].upper()+string[1:]
10 голосов
/ 11 октября 2009

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

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

One-вкладыш:

>>> ' '.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)
5 голосов
/ 17 мая 2017

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

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

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

3 голосов
/ 16 марта 2014

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

"MyAwesomeString".title()

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

{{ "MyAwesomeString"|title }}

или с помощью переменной:

{{ myvar|title }}
2 голосов
/ 11 ноября 2016

Предлагаемый метод 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'
...