web-dev-qa-db-ja.com

Python title()とアポストロフィ

.title()を使用して、アポストロフィを含むタイトルから正しい出力を取得する方法はありますか?例えば:

"john's school".title() --> "John'S School"

ここで正しいタイトルを取得するにはどうすればよいですか、"John's School"

38
David542

タイトルに行に複数の空白文字が含まれていない場合(折りたたまれます)、代わりに string.capwords() を使用できます。

>>> import string
>>> string.capwords("john's school")
"John's School"

EDIT:Chris Morganが以下に正しく述べているように、sep引数に" "を指定することで、空白の折りたたみの問題を軽減できます。 :

>>> string.capwords("john's    school", " ")
"John's    School"
68

「O」で始まるアイルランド語の名前など、一部の単一のアポストロフィの後に大文字が続くため、これは一般的なケースでは困難です。 string.capwords()は多くの場合機能しますが、引用符で囲まれたものはすべて無視します。 string.capwords( "johnのプリンシパルは 'no'")は、期待する結果を返しません。

>>> capwords("John's School")
"John's School"
>>> capwords("john's principal says,'no'")
"John's Principal Says,'no'"
>>> capwords("John O'brien's School")
"John O'brien's School"

さらに厄介な問題は、タイトル自体が適切な結果を生成しないことです。たとえば、アメリカで使用されている英語では、冠詞と前置詞は通常、タイトルや見出しで大文字になりません。 (シカゴスタイルマニュアル)。

>>> capwords("John clears school of spiders")
'John Clears School Of Spiders'
>>> "John clears school of spiders".title()
'John Clears School Of Spiders'

Easy_install titlecase module を使用すると、キャップワードの問題なしに、はるかに便利になり、好きなことを実行できます。もちろん、まだ多くのEdgeケースがありますが、個人的に作成されたバージョンについてあまり心配することなく、さらに進んでいきます。

>>> titlecase("John clears school of spiders")
'John Clears School of Spiders'
13
Art Taylor

title()では難しいと思います

別のことを試してみましょう:

def titlize(s):
    b = []
    for temp in s.split(' '): b.append(temp.capitalize())
    return ' '.join(b)

titlize("john's school")

// You get : John's School

お役に立てば幸いです。

5
Yugal Jindle

他の回答は役に立ち、より簡潔ですが、問題が発生する可能性があります。たとえば、文字列に新しい行やタブがある場合です。また、アポストロフィで始まる単語だけでなく、ハイフンでつながれた単語(通常のハイフンまたは改行しないハイフン)が問題になる場合もあります。ただし、正規表現を使用すると(正規表現置換引数の関数を使用)、次の問題を解決できます。

import re

def title_capitalize(match):
    text=match.group()
    i=0
    new_text=""
    capitalized=False
    while i<len(text):
        if text[i] not in {"’", "'"} and capitalized==False:
            new_text+=text[i].upper()
            capitalized=True
        else:
            new_text+=text[i].lower()
        i+=1
    return new_text

def title(the_string):
    return re.sub(r"[\w'’‑-]+", title_capitalize, the_string)

s="here's an apostrophe es. this string has multiple         spaces\nnew\n\nlines\nhyphenated words: and non-breaking   spaces, and a non‑breaking hyphen, as well as 'ords that begin with ’strophies; it\teven\thas\t\ttabs."
print(title(s))

とにかく、必要に応じて、これを編集して、バックティックや何を持っているかなどのさらなる問題を補正することができます。

前置詞、接続詞、冠詞など、タイトルの先頭または末尾にない限り、タイトルの大文字と小文字を区別する必要があると思われる場合は、このコードなどを試すことができます(ただし、あいまいな単語がいくつかあります。 'when)などのコンテキストで把握する必要があります。

import re

lowers={'this', 'upon', 'altogether', 'whereunto', 'across', 'between', 'and', 'if', 'as', 'over', 'above', 'afore', 'inside', 'like', 'besides', 'on', 'atop', 'about', 'toward', 'by', 'these', 'for', 'into', 'beforehand', 'unlike', 'until', 'in', 'aft', 'onto', 'to', 'vs', 'amid', 'towards', 'afterwards', 'notwithstanding', 'unto', 'while', 'next', 'including', 'thru', 'a', 'down', 'after', 'with', 'afterward', 'or', 'those', 'but', 'whereas', 'versus', 'without', 'off', 'among', 'because', 'some', 'against', 'before', 'around', 'of', 'under', 'that', 'except', 'at', 'beneath', 'out', 'amongst', 'the', 'from', 'per', 'mid', 'behind', 'along', 'outside', 'beyond', 'up', 'past', 'through', 'beside', 'below', 'during'}

def title_capitalize(match, use_lowers=True):
    text=match.group()
    lower=text.lower()
    if lower in lowers and use_lowers==True:
        return lower
    else:
        i=0
        new_text=""
        capitalized=False
        while i<len(text):
            if text[i] not in {"’", "'"} and capitalized==False:
                new_text+=text[i].upper()
                capitalized=True
            else:
                new_text+=text[i].lower()
            i+=1
        return new_text

def title(the_string):
    first=re.sub(r"[\w'’‑-]+", title_capitalize, the_string)
    return re.sub(r"(^[\w'’‑-]+)|([\w'’‑-]+$)", lambda match : title_capitalize(match, use_lowers=False), first)
2

私見、ベストアンサーは @Frédéricのもの です。ただし、文字列がすでに単語に分割されていて、その方法を知っている場合はstring.capwordsが実装されている場合、不要な参加手順を回避できます。

def capwords(s, sep=None):
    return (sep or ' ').join(
        x.capitalize() for x in s.split(sep)
    )

結果として、これを行うことができます。

# here my_words == ['Word1', 'Word2', ...]
s = ' '.join(Word.capitalize() for Word in my_words)
0
MarSoft