ChatGPT解决这个技术问题 Extra ChatGPT

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

s = 'the brown fox'

……在这里做点什么……

s 应该是:

'The Brown Fox'

最简单的方法是什么?


C
Community

字符串的 .title() 方法(ASCII 或 Unicode 都可以)执行以下操作:

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

但是,请注意带有嵌入撇号的字符串,如文档中所述。

该算法使用一个简单的独立于语言的单词定义作为一组连续的字母。该定义在许多情况下都有效,但它意味着缩写和所有格中的撇号形成单词边界,这可能不是预期的结果:>>> "他们是来自英国的比尔的朋友".title() "他们是比尔的朋友来自英国”


我避免使用 " ".join(w.capitalize() for w in s.split()) 之类的所有格问题
这对大多数字符串来说是不安全的,因为每个单词甚至所有格都会大写。
string.title() 有问题。例如,当您使用 "e g 3b" 时,所需的结果将是 "E G 3b"。但是,"e g 3b".title() 返回 "E G 3B"
请记住,这也会导致:In [2]: 'tEst'.title() Out[2]: 'Test'
很好的答案,并且评论强调,在 python 中,并非所有东西都按照您需要的方式运行,但总有方便的方法可以做到这一点。最方便的方法通常是导入专门构建的库,例如 python-titlecase
P
Peter Mortensen

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

Python documentation on capwords

使用 str.split() 将参数拆分为单词,使用 str.capitalize() 将每个单词大写,并使用 str.join() 连接大写单词。如果可选的第二个参数 sep 不存在或无,则空白字符的运行将替换为单个空格并删除前导和尾随空格,否则 sep 用于拆分和连接单词。


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'"
不过,在正常情况下,这比 title() 效果更好。在我的情况下,title() 会为带有重音符号或分音符号的名称返回错误的输出,而 capwords() 会正确处理它。
很好,但它仍然混淆了“英国/英国”的区别
@Chen Houwu,英国/英国是一个完美的反例。如何防止 Python 使用类似的方法小写现有的大写字母?
s
steveha

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

拆分为单词,对拆分组中的每个单词进行初始大写,然后重新加入。这会将分隔单词的空格更改为单个空格,无论它是什么。

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() 中进行非平凡的处理以产生最终结果!


+1 用于使用切片的解决方案。我需要在不改变其余单词大写的情况下将首字母大写的东西(例如,Foo 变为 foo,但 FOO 变为 fOO)。这是完美的。
capitalize 返回它的第一个字符大写,其余小写
@Vanuan,你是对的!文档字符串描述让我认为它所做的只是将第一个字母大写,但你对它的实际作用是正确的。我会编辑答案。谢谢你的提醒。
根据陈厚武回答中的文档,这似乎是 string.capwords 所做的。
在上面的答案中需要注意的是,我认为最好使用 s.split(' '),而不是使用 s.split()。这是因为如果字符串有一些双空格,并且您希望在加入时保持这些双空格, s.plit(' ') 将帮助您保持空格,而 s.split() 不会
a
aljgom

以下是不同方法的总结,以及一些需要注意的陷阱

它们适用于所有这些输入:

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

将句子拆分为单词并将第一个字母大写,然后将其重新组合在一起: # 小心多个空格和空字符串 # 对于空单词 w[0] 会导致索引错误,# 但是使用 w[:1] 我们会得到所需的空字符串 def cap_sentence(s): return ' '.join(w[:1].upper() + w[1:] for w in s.split(' '))

在不拆分字符串的情况下,检查空格以查找单词的开头 def cap_sentence(s): return ''.join( (c.upper() if i == 0 or s[i-1] == ' ' else c) 对于 i, c in enumerate(s) )

或者使用生成器: # 遍历字符串中的每个字符 # 并将第一个字符和空格后的任何字符大写 from itertools import chain def cap_sentence(s): return ''.join( (c.upper() if prev == ' ' else c) for c, prev in zip(s, chain(' ', s)) )

使用正则表达式,来自 steveha 的回答:# 匹配字符串或空格的开头,后跟非空格 import re def cap_sentence(s): return re.sub("(^|\s)(\S)" , λ m: m.group(1) + m.group(2).upper(), s)

现在,这些是发布的其他一些答案,如果我们将单词定义为句子的开头或空格后的任何内容,它们无法按预期工作:

.title() return s.title() # 不需要的输出: "foO baR" => "Foo Bar" "foo's bar" => "Foo'S Bar" "foo's1bar" => "Foo'S1Bar" "foo 1bar" => "Foo 1Bar"

.capitalize() 或 .capwords() return ' '.join(w.capitalize() for w in s.split()) # 或导入字符串 return string.capwords(s) # 不需要的输出:“foO baR” => "Foo Bar" "foo bar" => "Foo Bar" 使用 ' ' 进行拆分将修复第二个输出,但不是第一个 return ' '.join(w.capitalize() for w in s.split(' ' )) # 或导入字符串 return string.capwords(s, ' ') # 不想要的输出:"foO baR" => "Foo Bar"

.upper() 小心多个空格,这可以通过使用 ' ' 进行拆分来解决(如答案顶部所示) return ' '.join(w[0].upper() + w[1: ] for w in s.split()) # 不想要的输出:“foo bar”=>“Foo Bar”


+1 以获得全面的总结。我正在寻找一种仅将数字后面的单词(不是每个单词)大写的方法。您能否对您的答案进行补充以证明这一点?例如,lower 123 upper 应该返回 lower 123 Upper,其中 upper 大写,因为它跟在数字后面。我知道它超出了 OP 问题的范围,但对您已经广泛的答案来说是一个很好的补充。提前致谢。
在这种情况下,您可以修改上述一些方法以满足您的需要。但是,我不会将其添加为答案的一部分,因为这不是大多数人想要的。我会使用正则表达式版本,并使用 "([0-9]+)(\s+.)" 而不是 "(^|\s)(\S)" (匹配一个或多个数字,后跟一个或多个空格,以及后面的任何字符),或者如果您想将字符大写,则使用 "([0-9]+)(\s*.)"在数字后的“零个或多个”空格之后
我一定会调查它,这让我想到了另一种特殊情况:您将如何修改上面的代码片段以获取字符串,例如 WW1 - the great war 并输出 WW1 - The Great War 而不是 Ww1 ...。看到缩写的问题了吗?你愿意添加一些东西来证明这个案例吗?我一直在想这个问题,现在想不出办法。
上述第一种方法不会更改输入字符串中已经大写的字母,因此 WW1 将输出为 WW1
非常感谢,我一直在寻找能够以这种方式解决这个问题的东西,非常好的答案,一切都很好地解释了“参数 fooR”返回为“参数 FooR”现在我终于可以停止破坏我的小指来对抗 shift 键欢呼了从未来
a
ayhan

@jibberia anwser 的可复制粘贴版本:

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

无需建立清单。 str.join 接受生成器。
@warvariuc 您将如何更改此代码以利用生成器?
只需删除方括号,就像它完成 here
尽管@warvariuc 完美地提到了 join 接受 gen exp,但特别是在 str.join 的情况下,通常首选使用列表推导。这是因为 join 对参数进行了两次迭代,因此提供准备就绪列表比提供生成器更快。
@BhargavRao 为什么 str.join 需要对参数进行两次迭代?我刚刚检查过 - 它没有。虽然对于小序列列表理解确实更快。
B
Brad Larson

当解决方案简单且安全时,为什么还要使用连接和 for 循环使您的生活复杂化?

只需这样做:

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

因为可以有几个词。
是的,但通常我只想将第一个字母大写。这是一种方法。
你不会只使用 "the brown fox".capitalize() 吗?
@luckydonald 因为也许我不想把 'this is John' 变成 'This is john'
只是string.capitalize()不是更好的方法(基本上呼应@luckydonald)
j
jibberia

如果 str.title() 对您不起作用,请自己进行大写。

将字符串拆分为单词列表 将每个单词的首字母大写 将单词合并为单个字符串

单线:

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

此解决方案的一个有趣之处在于您丢失了任何特殊的空格。根据上下文可能并不重要。
值得指出的是,如果大写的句子或单词集包含单个字符单词,例如“a”或“I”,则此方法会失败。
D
Daniel Holmes

如果只想要第一个字母:

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

但是要将每个单词大写:

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

小心,因为 'hello New York'.capitalize()'Hello new york'
P
Peter Mortensen

如果访问 [1:],空字符串将引发错误。因此我会使用:

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

仅将第一个字母大写。


这不是 str.capitalize 的用途吗?
@Eugene,是的,但不幸的是,将所有其他可能不需要的字母大写。 :/
return title[:1].upper() + title[1:] 也会解决这个问题,因为像这样切片空字符串会给出 2 个空字符串,连接在一起会形成一个返回的空字符串
P
Peter Mortensen

尽管所有答案都已经令人满意,但我将尝试将两个额外的案例与之前的所有案例一起介绍。

如果空间不统一并且您想保持相同

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

感谢您强调非均匀空间的情况。上面的一些答案使用 s.split() 而不是 s.split(' ')。需要注意的是,对于非均匀空间,使用 s.split(' ') 将确保保持非均匀空间!再次感谢
这非常适用于空格不均匀的单词或以某个数字开头的单词。谢谢 :)
P
Peter Mortensen

正如 Mark 指出的,您应该使用 .title()

"MyAwesomeString".title()

但是,如果想让 Django 模板中的第一个字母大写,可以使用:

{{ "MyAwesomeString"|title }}

或使用变量:

{{ myvar|title }}

C
Community

建议的方法 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,则可能会出现错误。供参考:hackerrank problem
P
Peter Mortensen

要将单词大写...

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 中快速执行。
我不太喜欢 title(),因为它不处理撇号。 "I can't say".title() 给出 "I Can'T Say"
@Gary02127 我已经更新了答案,请看一下,也与您的问题域完美配合
O
Omar

你可以试试这个。简单整洁。

def cap_each(string):
    list_of_words = string.split(" ")

    for word in list_of_words:
        list_of_words[list_of_words.index(word)] = word.capitalize()

    return " ".join(list_of_words)

G
Gary02127

不要忽视留白。如果您想处理 'fred flinstone' 而得到的是 'Fred Flinstone' 而不是 'Fred Flinstone',那么您已经损坏了空白。上述一些解决方案会丢失空白。这是一个适用于 Python 2 和 3 并保留空白的解决方案。

def propercase(s):
    return ''.join(map(''.capitalize, re.split(r'(\s+)', s)))

A
Augustine Jose

.title() 方法不适用于所有测试用例,因此将 .capitalize()、.replace() 和 .split() 一起使用是每个单词首字母大写的最佳选择。

例如:def caps(y):

     k=y.split()
     for i in k:
        y=y.replace(i,i.capitalize())
     return y

P
PADYMKO

一个适用于 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.

此答案仅将句子的第一个字母大写。问题要求将句子中每个单词的首字母大写
P
Peter Mortensen

大写带有非均匀空格的字符串

我想补充@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)

..如果您的代码不是棕色和狐狸之间的空格,则您的代码无法补偿制表符;-)
D
David Buck

您的问题最简单的解决方案,它适用于我的情况:

import string
def solve(s):
    return string.capwords(s,' ') 
    
s=input()
res=solve(s)
print(res)

J
JonathanLoscalzo

另一种在线解决方案可能是:

" ".join(map(lambda d: d.capitalize(), word.split(' ')))

这个问题有 21 个现有的答案,包括一个获得最高票数、接受了超过 1200 票的答案。你确定你的解决方案还没有给出吗?如果不是,您为什么认为您的方法改进了已通过社区验证的现有提案?在 Stack Overflow 上提供解释总是有用的,但在问题已得到解决且令 OP 和社区都满意的情况下尤为重要。通过解释您的答案的不同之处以及何时可能更受欢迎,来帮助读者。
抱歉@JeremyCaney,但我没有在另一条评论中看到这个解决方案。虽然,我认为这个网站对答案有两个选择:投票或取消投票。如果您觉得我的解决方案没有用,请取消投票。但是,我再次认为这个平台是用于共享解决方案的,在这种情况下是一个 IMO,这是一个简单问题的简单解决方案。我不知道如果还有其他几个好的解决方案,它可能不会出现另一个。
@JeremyCaney 我找到了一些类似的答案:link。恭喜!在这种情况下,他使用的是正则表达式,而我使用的是 space character
我不知道为什么我有幸被你讲课。因为,这是一个简单的问题,需要一个简单的解决方案。我不知道为什么我收到了这个建议而没有其他人。不过还是谢谢
我曾在“低质量答案”审核队列中看到您的帖子,这是被标记为不是答案的帖子所在的位置,或者会触发某些自动启发式(例如,基于长度、缺乏解释等) .)。您的答案似乎有效,我确实投票保留了它。但我也想确定你对如何改进它有反馈。作为 Stack Overflow 的消费者,找到许多纯代码答案的问题可能会让人不知所措,因此解释为什么一种方法与其他答案不同(如果不是更可取)是非常有用的。
P
Peter Mortensen

如果你想缩小规模

# 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

U
Usman Maqbool

我真的很喜欢这个答案:

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

这太复杂了,你甚至去检查长度?!效率低下。