标题中的字符串带有例外


87

有没有在Python的标准方式标题字符的字符串(即词开始大写字符,所有剩余的套管字符有小写),但像离开的文章andinof小写?

Answers:


151

这有一些问题。如果使用拆分和合并,则某些空格字符将被忽略。内置的大写和标题方法不会忽略空格。

>>> 'There     is a way'.title()
'There     Is A Way'

如果句子以文章开头,则不希望标题的第一个单词小写。

请记住以下几点:

import re 
def title_except(s, exceptions):
    word_list = re.split(' ', s)       # re.split behaves as expected
    final = [word_list[0].capitalize()]
    for word in word_list[1:]:
        final.append(word if word in exceptions else word.capitalize())
    return " ".join(final)

articles = ['a', 'an', 'of', 'the', 'is']
print title_except('there is a    way', articles)
# There is a    Way
print title_except('a whim   of an elephant', articles)
# A Whim   of an Elephant

为什么有re必要?有一个"".split功能可以做到这一点。
wizzwizz4

1
@ wizzwizz4:str.split不考虑连续空间。re.split保留空间。因此,此功能不会占用任何空间。
dreerosaur

@dererosaur我以为那"".split()不是考虑他们,而是考虑了"".split(" ")
wizzwizz4

您的代码片段无法正常工作title_except('a whim of aN elephant', articles)。您可以使用word.lower() in exceptions过滤条件进行修复。
Dariusz Walczak

@dheerosaur我正在寻找一种将大写在文章和数字后面的单词都大写的方法。您能在答案中补充一点以证明这一点吗?例如2001 a Space Odyssey,return 2001 A Space Odyssey,其中的数字a大写。提前致谢。
ProGrammer

53

使用titlecase.py模块!仅适用于英语。

>>> from titlecase import titlecase
>>> titlecase('i am a foobar bazbar')
'I Am a Foobar Bazbar'

GitHub:https : //github.com/ppannuto/python-titlecase


1
如果要转换的字符串在其中的任何地方都包含数字,则titlecase模块不起作用。
Troy

1
@Troy似乎数字问题已解决,或者我没有遇到麻烦。例如:titlecase('one 4 two')->'One 4 Two'。现在titlecase('1one')->'1one',但是'1one'.title()->'1One'。尽管后面的例子是一个极端的例子,但我不确定'1One'是正确的标题。我也不太担心拿起我的语法书。
brent.payne 2014年

如果我在“百老汇大街321号”的情况下无法使用“百老汇大街321号”,则无法使用。使用上面由dreerosaur提出的解决方案,将产生“ 321 A Broadway Street”。
MoreScratch

也很好,它使标题中的首字母缩写保持不变。“创新TIaSR的发展”成为“创新TIaSR的发展”。
Matthias Arras

22

有以下方法:

>>> mytext = u'i am a foobar bazbar'
>>> print mytext.capitalize()
I am a foobar bazbar
>>> print mytext.title()
I Am A Foobar Bazbar

没有小写的文章选项。您可能必须自己编写代码,可能要使用要降低的文章列表。


titlecase.py小写文章。
TRS-80

14

斯图尔特·科尔维尔取得了一个Python端口由约翰格鲁伯写一个Perl脚本转换成字符串标题的情况下,但避免了资本基于来自纽约时报的规则手册的风格,以及对几种特殊情况的餐饮小词。

这些脚本的一些巧妙之处:

  • 它们大写小写的单词,例如if,in,of,on等,但如果在输入中错误地大写,则会取消大写。

  • 脚本假定使用大写字母而不是第一个字符的单词已经正确大写。这意味着他们将只留下“ iTunes”之类的字眼,而不是将其改成“ iTunes”或更糟的是“ Itunes”。

  • 他们跳过任何带有线点的单词;“ example.com”和“ del.icio.us”将保持小写。

  • 他们有专门针对特殊情况的硬编码骇客,例如“ AT&T”和“ Q&A”,两者都包含小写字母(at和a),通常应使用小写字母。

  • 标题的第一个和最后一个词始终大写,因此诸如“无所畏惧”之类的输入将变为“无所畏惧”。

  • 冒号后面的一个小词将大写。

您可以在此处下载。


4
capitalize (word)

这应该做。我有不同的看法。

>>> mytext = u'i am a foobar bazbar'
>>> mytext.capitalize()
u'I am a foobar bazbar'
>>>

如上述答复所述,您必须自定义大写字母:

mytext =我是foobar bazbar'

def xcaptilize(word):
    skipList = ['a', 'an', 'the', 'am']
    if word not in skipList:
        return word.capitalize()
    return word

k = mytext.split(" ") 
l = map(xcaptilize, k)
print " ".join(l)   

这个输出

I am a Foobar Bazbar

那不是我想要的 我想获得“我是Foobar Bazbar”
yassin 2010年

@Yassin Ezbakhe:编辑了我的答案,这应该对您有用。文章列表可以从任何词典中轻松找到
pyfunc

2

Python 2.7的title方法存在一个缺陷。

value.title()

当值是Carpenter 's Assistant时将返回Carpenter 'S Assistant

最好的解决方案可能是@BioGeek的解决方案,其中使用了Stuart Colville的标题栏。这与@Etienne提出的解决方案相同。


1
 not_these = ['a','the', 'of']
thestring = 'the secret of a disappointed programmer'
print ' '.join(word
               if word in not_these
               else word.title()
               for word in thestring.capitalize().split(' '))
"""Output:
The Secret of a Disappointed Programmer
"""

标题以大写字母开头,与文章不匹配。


1

使用列表理解和三元运算符的单线

reslt = " ".join([word.title() if word not in "the a on in of an" else word for word in "Wow, a python one liner for titles".split(" ")])
print(reslt)

分解:

for word in "Wow, a python one liner for titles".split(" ") 将字符串拆分为一个列表并启动for循环(在列表理解中)

word.title() if word not in "the a on in of an" else word 使用本机方法 title()如果不是文章,则为字符串加上大小写标题

" ".join 用(空格)分隔符连接列表元素


0

首字母缩略词是一种未被考虑的重要情况(如果您明确提供首字母缩略词作为例外,则python-titlecase解决方案可以处理首字母缩略词)。相反,我宁愿简单地避免使用套管。通过这种方法,已经是大写的首字母缩略词保留为大写。以下代码是对Dererosaur最初提供的代码的修改。

# This is an attempt to provide an alternative to ''.title() that works with 
# acronyms.
# There are several tricky cases to worry about in typical order of importance:
# 0. Upper case first letter of each word that is not an 'minor' word.
# 1. Always upper case first word.
# 2. Do not down case acronyms
# 3. Quotes
# 4. Hyphenated words: drive-in
# 5. Titles within titles: 2001 A Space Odyssey
# 6. Maintain leading spacing
# 7. Maintain given spacing: This is a test.  This is only a test.

# The following code addresses 0-3 & 7.  It was felt that addressing the others 
# would add considerable complexity.


def titlecase(
    s,
    exceptions = (
        'and', 'or', 'nor', 'but', 'a', 'an', 'and', 'the', 'as', 'at', 'by',
        'for', 'in', 'of', 'on', 'per', 'to'
    )
):
    words = s.strip().split(' ')
        # split on single space to maintain word spacing
        # remove leading and trailing spaces -- needed for first word casing

    def upper(s):
        if s:
            if s[0] in '‘“"‛‟' + "'":
                return s[0] + upper(s[1:])
            return s[0].upper() + s[1:]
        return ''

    # always capitalize the first word
    first = upper(words[0])

    return ' '.join([first] + [
        word if word.lower() in exceptions else upper(word)
        for word in words[1:]
    ])


cases = '''
    CDC warns about "aggressive" rats as coronavirus shuts down restaurants
    L.A. County opens churches, stores, pools, drive-in theaters
    UConn senior accused of killing two men was looking for young woman
    Giant asteroid that killed the dinosaurs slammed into Earth at ‘deadliest possible angle,’ study reveals
    Maintain given spacing: This is a test.  This is only a test.
'''.strip().splitlines()

for case in cases:
    print(titlecase(case))

运行时,它将产生以下内容:

CDC Warns About "Aggressive" Rats as Coronavirus Shuts Down Restaurants L.A. County Opens Churches, Stores, Pools, Drive-in Theaters
UConn Senior Accused of Killing Two Men Was Looking for Young Woman
Giant Asteroid That Killed the Dinosaurs Slammed Into Earth at ‘Deadliest Possible Angle,’ Study Reveals
Maintain Given Spacing: This Is a Test.  This Is Only a Test.
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.