İstisnalarla bir dizeye başlık ekleme


87

Bir dize TitleCase için Python standart bir yol ama gibi bırakarak yazılar (yani kelimeler Büyük karakterlerle başlayan tüm kalan kasalı karakterler küçük harf var,) var mı and, inve ofküçük harfli?

Yanıtlar:


151

Bununla ilgili birkaç sorun var. Böl ve birleştir kullanırsanız, bazı beyaz boşluk karakterleri göz ardı edilecektir. Yerleşik büyük harf yapma ve başlık yöntemleri beyaz boşluğu göz ardı etmez.

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

Bir cümle bir makaleyle başlıyorsa, başlığın ilk kelimesinin küçük harf olmasını istemezsiniz.

Bunları akılda tutarak:

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

Neden regereklidir? "".splitAynı şeyi yapan bir işlev var.
wizzwizz4

1
@ wizzwizz4: str.splitbitişik boşlukları dikkate almaz. re.splitboşlukları tutar. Yani, bu işlev hiç yer kaplamaz.
dheerosaur

@dheerosaur "".split()Onları dikkate almadığını düşündüm ama "".split(" ")yaptım.
wizzwizz4

Snippet'iniz durum için düzgün çalışmayacaktır title_except('a whim of aN elephant', articles). word.lower() in exceptionsDüzeltmek için filtreleme koşulunu kullanabilirsiniz .
Dariusz Walczak

@dheerosaur Sadece bir makaleden değil, aynı zamanda bir numaradan sonra gelen herhangi bir kelimeyi büyük harfle yazmanın bir yolunu arıyorum. Cevabınıza bunu gösteren bir ekleme yapabilir misiniz? Örneğin , bir sayıyı takip ettiği için büyük harfle yazıldığında 2001 a Space Odysseydöndürülmelidir . Şimdiden teşekkürler. 2001 A Space Odysseya
ProGrammer

54

Titlecase.py modülünü kullanın ! Yalnızca İngilizce için çalışır.

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

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


1
Eğer dönüştürdüğünüz dizge herhangi bir yerde bir sayı içeriyorsa, titlecase modülü çalışmaz.
Troy

1
@Troy, sayı sorunu çözülmüş gibi görünüyor veya kenar davanıza ulaşmadım. Ör: titlecase ('bir 4 iki') -> 'Bir 4 İki'. Şimdi titlecase ('1one') -> '1one', ancak '1one'.title () ->' 1One '. ancak bu sonraki durum uç bir durumdur ve "1One" nin doğru başlık olduğundan emin değilim. Ayrıca gramer kitabımı alacak kadar endişelenmiyorum.
brent.payne

"321 a Broadway Street" aldığım "321 A BROADWAY STREET" durumunda çalışmaz. Yukarıda dheerosaur tarafından önerilen çözümü kullanarak "321 A Broadway Street" ortaya çıkıyor.
MoreScratch

Ayrıca güzel, başlıkta kısaltmalara dokunulmamış. 'Yenilikçi TIaSR'nin geliştirilmesi', 'Yenilikçi TIaSR'nin Geliştirilmesi' olur.
Matthias Arras

22

Şu yöntemler var:

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

Küçük harfli makale seçeneği yoktur. Muhtemelen düşürmek istediğiniz makalelerin bir listesini kullanarak bunu kendiniz kodlamanız gerekir.


titlecase.py küçük harfli makaleler.
TRS-80

14

Stuart Colville, dizeleri başlık durumuna dönüştürmek için John Gruber tarafından yazılan bir Perl betiğinin Python bağlantı noktasını yaptı , ancak New York Times Stil El Kitabındaki kurallara göre küçük kelimelerin büyük harfle yazılmasının yanı sıra birkaç özel durum için yiyecek ve içecek sağlamaktan kaçınıyor.

Bu senaryoların bazı zekası:

  • if, in, of, on , vb. gibi küçük sözcükleri büyük harfle yazarlar, ancak girdide hatalı bir şekilde büyük harfle yazıldıklarında büyük harfle yazılmazlar.

  • komut dosyaları, ilk karakter dışında büyük harf içeren kelimelerin zaten doğru şekilde büyük harfle yazıldığını varsayar. Bu, "iTunes" gibi bir kelimeyi "iTunes" ya da daha kötüsü "Itunes" ile karıştırmak yerine tek başına bırakacakları anlamına gelir.

  • çizgi noktalı kelimeleri atlarlar; "Example.com" ve "del.icio.us" küçük harf olarak kalacaktır.

  • "AT&T" ve "Q&A" gibi, her ikisi de normalde küçük harf olması gereken küçük sözcükler (at ve a) içeren, özellikle garip durumlarla ilgilenmek için sabit kodlanmış hack'lere sahiptirler.

  • Başlığın ilk ve son kelimesi her zaman büyük harfle yazılır, bu nedenle "Korkacak hiçbir şey yok" gibi girdiler "Korkacak Hiçbir Şey" e dönüştürülür.

  • İki noktadan sonraki küçük bir kelime büyük harfle yazılır.

Buradan indirebilirsiniz .


4
capitalize (word)

Bu yapmalı. Ben farklı anlıyorum.

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

Tamam, yukarıdaki yanıtta da belirtildiği gibi, özel bir büyük harf yapmanız gerekir:

mytext = u'i bir foobar bazbarım '

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)   

Bu çıktılar

I am a Foobar Bazbar

İstediğim bu değil. Ben "Ben bir Falanca Bazbar duyuyorum" almak istiyorum
Yasin'i

@Yassin Ezbakhe: Cevabımı düzenledim, bu senin için çalışmalı. Makalelerin listesi herhangi bir sözlükten kolayca kaldırılabilir
pyfunc

2

Python 2.7'nin başlık yönteminde bir kusur var.

value.title()

'Carpenter dönecektir S değeri Carpenter olduğunda Yardımcısı' ın Asistanı

En iyi çözüm muhtemelen Stuart Colville'den titlecase kullanan @ BioGeek'ten gelen çözümdür. @Etienne tarafından önerilen çözümün aynısı.


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

Başlık büyük harfle yazılan kelimeyle başlıyor ve bu makale ile uyuşmuyor.


1

Liste anlama ve üçlü operatörü kullanan tek satırlık

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)

Yıkmak:

for word in "Wow, a python one liner for titles".split(" ") Dizeyi bir listeye böler ve bir for döngüsü başlatır (listede comprehenstion)

word.title() if word not in "the a on in of an" else word yerel yöntemi kullanır title()Bir makale değilse dizeyi büyük / küçük harf olarak adlandırmak için

" ".join (boşluk) ayırıcısı ile liste öğelerini birleştirir


0

Dikkate alınmayan önemli bir durum kısaltmalardır (python-titlecase çözümü, kısaltmaları açıkça istisna olarak sağlarsanız işleyebilir). Bunun yerine basitçe kasayı kapatmayı tercih ederim. Bu yaklaşımla, zaten büyük olan kısaltmalar büyük harf olarak kalır. Aşağıdaki kod, orijinal olarak dheerosaur tarafından sağlananın bir modifikasyonudur.

# 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))

Çalıştırıldığında aşağıdakileri üretir:

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.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.