例外のある文字列のタイトルケース


87

文字列をタイトルケースにするPythonでの標準的な方法はあります(つまり、言葉は残りのすべてのケース入りの文字が小文字を持って、大文字で始まる)が、のような記事を残しandinof小文字?

回答:


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

1
@ wizzwizz4:str.split連続したスペースは考慮されません。re.splitスペースを保持します。したがって、この関数はスペースを消費しません。
dheerosaur 2017年

@dheerosaur私"".split()はそれを考慮しなかったと思いましたが、考慮しまし"".split(" ")た。
wizzwizz4 2017年

title_except('a whim of aN elephant', articles)場合によっては、スニペットが正しく機能しません。word.lower() in exceptionsフィルタリング条件を使用して修正できます。
Dariusz Walczak 2017

@dheerosaur記事だけでなく、数字に続く単語を大文字にする方法を探しています。これを実証するあなたの答えに追加をすることができますか?たとえば、2001 a Space Odysseyを返す必要2001 A Space Odysseyがありaます。ここで、は数字の後に大文字で表記されます。前もって感謝します。
ProGrammer 2018年

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モジュールは機能しません。
トロイ

1
@Troy番号の問題が修正されたか、エッジケースにヒットしなかったようです。例:titlecase( 'one 4 two')-> 'One 4 Two'。ここで、titlecase( '1one')-> '1one'ですが、 '1one'.title()->' 1One 'です。この後者のケースはエッジケースであり、「1One」が正しいタイトルであるかどうかはわかりませんが。また、文法書を手に入れるほど心配していません。
brent.payne 2014

「321ABROADWAYStreet」を取得した「321ABROADWAYSTREET」の場合は動作しません。上記のdheerosaurによって提案されたソリューションを使用すると、「321 ABroadwayStreet」が生成されます。
MoreScratch 2016年

また、タイトルの頭字語はそのままです。「革新的なTIaSRの開発」は「革新的なTIaSRの開発」になります。
マティアスアラス

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

Stuart Colvilleは、文字列をタイトルケースに変換するために、John Gruberによって作成されたPerlスクリプトのPythonポート作成しましたが、ニューヨークタイムズのスタイルマニュアルのルールに基づいて小さな単語を大文字にすることや、いくつかの特殊なケースに対応することを避けています。

これらのスクリプトの巧妙さのいくつか:

  • 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 = u '私は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

それは私が望むものではありません。「私はFoobarBazbarです」を取得したい
yassin 2010

@Yassin Ezbakhe:私の答えを編集しました、これはあなたのために働くはずです。記事のリストは、どの辞書からでも簡単に削除できます
pyfunc 2010

2

Python2.7のtitleメソッドには欠陥があります。

value.title()

「カーペンター戻りますS値はカーペンターのときアシスタントを」sのアシスタント

最善の解決策は、おそらくStuartColvilleのタイトルケースを使用した@BioGeekの解決策です。これは@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 wordtitle()冠詞でない場合は、ネイティブメソッドを使用して文字列にタイトルを付けます

" ".join リスト要素を(スペース)の区切り文字で結合します


0

考慮されていない重要なケースの1つは頭字語です(例外として明示的に指定した場合、python-titlecaseソリューションは頭字語を処理できます)。代わりに、単にダウンケーシングを避けることを好みます。このアプローチでは、すでに大文字になっている頭字語は大文字のままになります。次のコードは、dheerosaurによって最初に提供されたコードを変更したものです。

# 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.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.