Titlecasing string dengan pengecualian

87

Apakah ada cara standar dalam Python untuk titlecase string (yaitu kata-kata mulai dengan karakter huruf besar, semua karakter cased tersisa memiliki huruf kecil) tetapi meninggalkan artikel seperti and, in, dan oflowercased?

yassin
sumber

Jawaban:

151

Ada beberapa masalah dengan ini. Jika Anda menggunakan pisahkan dan gabung, beberapa karakter spasi putih akan diabaikan. Metode kapitalisasi dan judul bawaan tidak mengabaikan spasi.

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

Jika kalimat dimulai dengan sebuah artikel, Anda tidak ingin kata pertama dari sebuah judul menggunakan huruf kecil.

Ingatlah ini:

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
dheerosaurus
sumber
Mengapa reperlu? Ada "".splitfungsi yang melakukan hal yang sama.
wizzwizz4
1
@ wizzwizz4: str.splittidak mempertimbangkan spasi yang bersebelahan. re.splitmempertahankan ruang. Jadi, fungsi ini tidak memakan tempat.
dheerosaurus
@dheerosaur Saya pikir itu "".split()tidak mempertimbangkan mereka tetapi "".split(" ")melakukannya.
wizzwizz4
Cuplikan Anda tidak akan berfungsi dengan benar untuk title_except('a whim of aN elephant', articles)kasus. Anda dapat menggunakan word.lower() in exceptionskondisi pemfilteran untuk memperbaikinya.
Dariusz Walczak
@dheerosaur Saya mencari cara untuk menggunakan huruf besar pada kata apa pun yang mengikuti tidak hanya artikel tetapi juga angka. Bisakah Anda menambahkan jawaban Anda yang menunjukkan hal ini? Misalnya 2001 a Space Odysseyharus kembali 2001 A Space Odyssey, di mana adikapitalisasi seperti mengikuti angka. Terima kasih sebelumnya.
ProGrammer
54

Gunakan modul titlecase.py ! Bekerja hanya untuk bahasa Inggris.

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

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

Etienne
sumber
1
Modul titlecase tidak berfungsi jika string yang Anda ubah berisi angka di mana pun di dalamnya.
Troy
1
@ Hancurkan tampaknya masalah nomor sudah diperbaiki, atau saya tidak mengenai kasus tepi Anda. Contoh: titlecase ('one 4 two') -> 'One 4 Two'. Sekarang titlecase ('1one') -> '1one', but '1one'.title () ->' 1One '. meskipun kasus selanjutnya ini adalah kasus tepi dan saya tidak yakin '1One' adalah judul yang benar. Saya juga tidak cukup khawatir untuk mengambil buku tata bahasa saya.
brent.payne
Tidak akan berhasil dalam kasus "321 A BROADWAY STREET" di mana saya mendapatkan "321 a Broadway Street". Menggunakan solusi yang diusulkan oleh dheerosaur di atas menghasilkan "321 A Broadway Street".
MoreScratch
Juga bagus, itu membuat akronim dalam judul tidak tersentuh. 'Pengembangan TIaSR inovatif' menjadi 'Pengembangan TIaSR Inovatif'.
Matthias Arras
22

Ada beberapa metode ini:

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

Tidak ada opsi artikel huruf kecil. Anda harus mengkodekannya sendiri, mungkin dengan menggunakan daftar artikel yang ingin Anda turunkan.

nosklo.dll
sumber
titlecase.py artikel huruf kecil.
TRS-80
14

Stuart Colville telah membuat port Python dari skrip Perl yang ditulis oleh John Gruber untuk mengubah string menjadi kapitalisasi judul, tetapi menghindari penggunaan huruf kecil berdasarkan aturan gaya New York Times Manual, serta melayani beberapa kasus khusus.

Beberapa kepintaran dari skrip ini:

  • mereka menggunakan huruf besar untuk kata-kata kecil seperti if, in, of, on , dll., tetapi akan menghapus penggunaan huruf besar jika salah kapitalisasi dalam input.

  • skrip mengasumsikan bahwa kata-kata dengan huruf kapital selain karakter pertama sudah menggunakan huruf besar dengan benar. Ini berarti mereka akan meninggalkan kata seperti "iTunes" saja, daripada mengacaukannya menjadi "ITunes" atau, lebih buruk, "Itunes".

  • mereka melewatkan kata apa pun dengan titik-titik garis; "Example.com" dan "del.icio.us" akan tetap menggunakan huruf kecil.

  • mereka memiliki kode keras peretasan khusus untuk menangani kasus-kasus aneh, seperti “AT&T” dan “Q&A”, keduanya berisi kata-kata kecil (at dan a) yang biasanya harus huruf kecil.

  • Kata pertama dan terakhir dari judul selalu menggunakan huruf besar, sehingga masukan seperti “Tidak ada yang perlu ditakuti” akan diubah menjadi “Tidak Ada yang Perlu Ditakuti”.

  • Kata kecil setelah titik dua akan menggunakan huruf besar.

Anda bisa mendownloadnya disini .

BioGeek
sumber
4
capitalize (word)

Ini harus dilakukan. Saya mendapatkannya secara berbeda.

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

Ok seperti yg dibilang di atas, anda harus membuat custom kapitalisasi:

mytext = u'i am a 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)   

Output ini

I am a Foobar Bazbar
pyfunc
sumber
Bukan itu yang saya inginkan. Saya ingin mendapatkan "I am a Foobar Bazbar"
yassin
@Yassin Ezbakhe: Mengedit jawaban saya, ini akan bekerja untuk Anda. Daftar artikel dapat dengan mudah diangkat dari kamus manapun
pyfunc
2

Metode judul Python 2.7 memiliki kekurangan di dalamnya.

value.title()

akan kembali Carpenter ' S Asisten ketika nilai adalah Carpenter' s Asisten

Solusi terbaik mungkin adalah dari @BioGeek menggunakan titlecase dari Stuart Colville. Solusi mana yang sama yang dikemukakan oleh @Etienne.

pembuat perahu
sumber
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
"""

Judul dimulai dengan kata kapital dan tidak sesuai dengan artikel.

Tony Veijalainen
sumber
1

One-liner menggunakan pemahaman daftar dan operator terner

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)

Kerusakan:

for word in "Wow, a python one liner for titles".split(" ") Memisahkan string menjadi daftar dan memulai perulangan for (dalam pemahaman daftar)

word.title() if word not in "the a on in of an" else word menggunakan metode asli title() untuk memberi judul case string jika itu bukan artikel

" ".join menggabungkan elemen daftar dengan pemisah (spasi)

pengguna7297223
sumber
0

Satu kasus penting yang tidak dipertimbangkan adalah akronim (solusi python-titlecase dapat menangani akronim jika Anda secara eksplisit memberikannya sebagai pengecualian). Saya lebih suka menghindari down-casing. Dengan pendekatan ini, akronim yang sudah dalam huruf besar tetap menggunakan huruf besar. Kode berikut adalah modifikasi dari yang aslinya disediakan oleh 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))

Saat dijalankan, ini menghasilkan yang berikut:

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.
Agustus Barat
sumber