如何将字符串中每个单词的首字母大写?


Answers:


985

.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 2013年

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'
Jonas Libbrecht

4
很好的答案和评论强调了在python中,并非所有事物都能按照您需要的方式运行,但是总有便捷的方法可以做到这一点。最方便的方法通常是导入专门构建的库,例如python-titlecase
Aaron3468 '18

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"

capwordspython文档中

使用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()
houcros

很好,但仍然弄乱了“英国/英国”的区别
Jonath P

104

仅仅因为这种事情对我来说很有趣,所以这里有另外两个解决方案。

拆分为单词,对拆分组中的每个单词进行大写,然后重新加入。不管是什么,这都会将将单词分隔的空白变为单个空白。

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

使用正则表达式匹配字符串的开头,或使用空格分隔单词,再加上一个非空格字符;用括号标记“匹配组”。编写一个函数,该函数接受一个match对象,并以大写形式返回空白的空白匹配组和非空白的字符匹配组。然后使用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
大写返回其首字符大写,其余小写
Vanuan 2012年

@Vanuan,你是对的!doc字符串描述使我认为它所做的只是将首字母大写,但是您对它的实际用途是正确的。我将编辑答案。谢谢你的提醒。
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,return lower 123 Upper,其中的数字upper大写。我知道这超出了OP的问题范围,但却是您已经广泛的答案的一个不错的附加。提前致谢。
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 exp 方面很完美str.join,但特别是在通常情况下,最好使用列表理解。这是因为join对参数进行两次迭代,因此提供现成的列表而不是生成器更快。
Bhargav饶

1
@BhargavRao为什么str.join需要对参数进行两次迭代?我刚刚检查了-事实并非如此。尽管对于小序列,列表理解确实确实更快。
warvariuc

12

当解决方案既简单又安全时,为什么要使join和for循环使您的生活复杂化?

只是这样做:

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

2
因为可以有几个字。
Arnaud

1
是的,但通常我只想大写第一个字母。这是一种做到这一点的方法。
Deleet '16

1
那您不就用"the brown fox".capitalize()吗?
luckydonald 2016年

2
@luckydonald因为也许我不想'this is John'变成'This is john'
janek37 '17

这不是简单地执行此操作的更好方法string.capitalize()(本质上是回声@luckydonald)
Hassan Baig,

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 2011年

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是的,但是不幸的是,将所有其他字母都用小写大写,这可能是不希望的。:/
Wim Feijen

return title[:1].upper() + title[1:]也将解决该问题,因为将这样的空字符串切成薄片将得到2个空字符串,将它们连接在一起将得到一个空字符串,然后将其返回
aljgom

3

正如Mark所指出的,您应该使用.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,则可能会发生错误。供参考:hackerrank问题
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('')将确保保持非均匀空间!再次感谢
manpikin

这非常适合空格不均的单词或以数字开头的单词。谢谢:)
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(),因为它不处理撇号。“我不能说” .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:]时会导致错误。可能有更好的方法来执行此操作,但是我必须添加if len(s)> 0,例如

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

2
这太复杂了,您甚至还要检查长度吗?!效率低下。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.