ชื่อเรื่องการใส่สตริงที่มีข้อยกเว้น


87

มีวิธีมาตรฐานในหลามเพื่อ titlecase สตริง (เช่นคำเริ่มต้นด้วยตัวอักษรตัวพิมพ์ใหญ่ตัวละครใส่ซองที่เหลือทั้งหมดมีตัวพิมพ์เล็ก) แต่บทความออกเหมือนand, inและoflowercased?

คำตอบ:


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รักษาช่องว่าง ดังนั้นฟังก์ชันนี้จึงไม่กินช่องว่างใด ๆ
dheerosaur

@dheerosaur ฉันคิดว่านั่น"".split()ไม่ได้พิจารณาพวกเขา แต่"".split(" ")ทำ
wizzwizz4

ตัวอย่างข้อมูลของคุณทำงานไม่ถูกต้องสำหรับtitle_except('a whim of aN elephant', articles)กรณี คุณสามารถใช้word.lower() in exceptionsเงื่อนไขการกรองเพื่อแก้ไขได้
Dariusz Walczak

@dheerosaur ฉันกำลังมองหาวิธีใช้ตัวพิมพ์ใหญ่คำใด ๆ ที่ตามมาไม่เพียง แต่บทความ แต่ยังรวมถึงตัวเลขด้วย คุณสามารถเพิ่มคำตอบของคุณที่แสดงให้เห็นถึงสิ่งนี้ได้หรือไม่? เช่น2001 a Space Odysseyควรส่งคืน2001 A Space Odysseyโดยที่aเป็นตัวพิมพ์ใหญ่ตามตัวเลข ขอบคุณล่วงหน้า.
ProGrammer

54

ใช้โมดูล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
โมดูลหัวเรื่องจะไม่ทำงานหากสตริงที่คุณกำลังแปลงมีตัวเลขอยู่ที่ใดก็ได้
ทรอย

1
@ ทรอยดูเหมือนว่าปัญหาเรื่องตัวเลขจะได้รับการแก้ไขแล้วหรือฉันไม่ได้โดนกรณีของคุณ เช่น titlecase ('one 4 two') -> 'One 4 Two' ตอนนี้ titlecase ('1one') -> '1one' แต่ '1one'.title () ->' 1One ' แม้ว่ากรณีหลังนี้จะเป็นแบบ edge และฉันไม่แน่ใจว่า '1One' คือชื่อที่ถูกต้อง ฉันยังกังวลไม่พอที่จะคว้าหนังสือไวยากรณ์ของฉัน
brent.payne

จะใช้ไม่ได้ในกรณีของ "321 A BROADWAY STREET" ที่ฉันได้รับ "321 a Broadway Street" การใช้โซลูชันที่เสนอโดย dheerosaur ข้างต้นทำให้เกิด "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

Stuart Colville ได้สร้างพอร์ต Pythonของสคริปต์ Perl ที่เขียนโดย John Gruberเพื่อแปลงสตริงเป็นตัวพิมพ์ใหญ่ แต่หลีกเลี่ยงการใช้อักษรตัวพิมพ์ใหญ่ตามกฎจาก New York Times Manual of style รวมถึงการจัดเลี้ยงสำหรับกรณีพิเศษต่างๆ

ความชาญฉลาดบางประการของสคริปต์เหล่านี้:

  • พวกเขาใช้ตัวพิมพ์ใหญ่คำเล็ก ๆ เช่นif, in, of, onเป็นต้น แต่จะยกเลิกการใช้อักษรตัวพิมพ์ใหญ่หากใช้อักษรตัวพิมพ์ใหญ่ผิดพลาด

  • สคริปต์จะถือว่าคำที่มีอักษรตัวพิมพ์ใหญ่นอกเหนือจากอักขระตัวแรกได้รับการใช้อักษรตัวพิมพ์ใหญ่อย่างถูกต้องแล้ว ซึ่งหมายความว่าพวกเขาจะทิ้งคำอย่าง“ iTunes” ไว้เพียงอย่างเดียวแทนที่จะเปลี่ยนเป็น“ iTunes” หรือที่แย่กว่านั้นคือ“ iTunes”

  • พวกเขาข้ามคำใด ๆ ที่มีจุดเส้น “ example.com” และ“ del.icio.us” จะยังคงเป็นตัวพิมพ์เล็ก

  • พวกเขามีแฮ็กที่เข้ารหัสโดยเฉพาะเพื่อจัดการกับกรณีแปลก ๆ เช่น“ AT&T” และ“ Q&A” ซึ่งทั้งสองคำนี้มีคำเล็ก ๆ (ที่และ a) ซึ่งโดยปกติควรเป็นตัวพิมพ์เล็ก

  • คำแรกและคำสุดท้ายของชื่อเรื่องจะเป็นตัวพิมพ์ใหญ่เสมอดังนั้นการป้อนข้อมูลเช่น“ ไม่มีอะไรต้องกลัว” จะกลายเป็น“ ไม่มีอะไรต้องกลัว”

  • คำเล็ก ๆ หลังเครื่องหมายจุดคู่จะเป็นตัวพิมพ์ใหญ่

คุณสามารถดาวน์โหลดได้ที่นี่


4
capitalize (word)

สิ่งนี้ควรทำ ฉันเข้าใจมันแตกต่างกัน

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

ตกลงตามที่กล่าวไว้ในคำตอบข้างต้นคุณต้องสร้างตัวพิมพ์ใหญ่ที่กำหนดเอง

mytext = u'i เป็น 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

@Yassin Ezbakhe: แก้ไขคำตอบของฉันสิ่งนี้น่าจะเหมาะกับคุณ รายชื่อบทความสามารถยกได้อย่างง่ายดายจากพจนานุกรมใด ๆ
pyfunc

2

วิธีการตั้งชื่อของ Python 2.7 มีข้อบกพร่อง

value.title()

จะส่งคืน Carpenter ' S Assistant เมื่อค่าเป็นผู้ช่วยของ Carpenter

ทางออกที่ดีที่สุดน่าจะเป็นของ @BioGeek โดยใช้ titlecase จาก 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(" ") แยกสตริงออกเป็นรายการและเริ่มต้นสำหรับการวนซ้ำ (ในรายการเปรียบเทียบ)

word.title() if word not in "the a on in of an" else wordใช้วิธีเนทีฟtitle()เพื่อตั้งชื่อกรณีของสตริงหากไม่ใช่บทความ

" ".join รวมองค์ประกอบรายการด้วยตัวแยกของ (ช่องว่าง)


0

กรณีสำคัญอย่างหนึ่งที่ไม่ได้รับการพิจารณาคือคำย่อ (โซลูชัน 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.