Заголовок рядка за винятком


87

Є стандартний спосіб в Python для titlecase рядки (тобто слова починаються з великими літерами, всі інші символи мають обсаджені в нижньому регістр) , але залишивши статті , як and, inі ofмалі?

Відповіді:


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

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
Модуль заголовка не працює, якщо рядок, який ви перетворюєте, містить де-небудь число.
Троя

1
@Troy, здається, проблема з номером виправлена, або я не потрапив у твій край. Приклад: заголовок ("один 4 два") -> "Один 4 два". Тепер заголовок ('1one') -> '1one', але '1one'.title () ->' 1One '. хоча цей пізніший випадок є крайовим, і я не впевнений, що '1One' є правильним заголовком. Я також не настільки стурбований, щоб взяти свою граматику.
brent.payne

Не буде працювати у випадку з "321 A BROADWAY STREET", де я отримую "321 a Broadway Street". Використовуючи запропоноване вище рішення герозавра, виходить "321 A Broadway Street".
MoreScratch

Також приємно, це залишає абревіатури у назві незайманими. "Розвиток інноваційного 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

Стюарт Колвілл створив порт Python для сценарію Perl, написаного Джоном Грубером для перетворення рядків у регістр заголовка, але уникає великих літер на основі правил стилю з посібника New York Times, а також обслуговування декількох особливих випадків.

Деякі хитрощі цих сценаріїв:

  • вони пишуть маленькі слова, такі як 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'i am 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: Відредагував мою відповідь, це має працювати для вас. Список статей можна легко
вилучити

2

Метод заголовка Python 2.7 має недолік.

value.title()

повернуся Карпентер « S Assistant , коли значення Карпентера» сек помічник

Найкраще рішення - це, мабуть, рішення від @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 word використовує рідний метод title() для заголовка рядка, якщо це не стаття

" ".join приєднує елементи списку за допомогою сепаратора (пробілу)


0

Одним із важливих випадків, який не розглядається, є абревіатури (рішення python-titlecase може обробляти абревіатури, якщо ви явно надаєте їх як винятки). Натомість я вважаю за краще просто уникати обсадних труб. При такому підході абревіатури, які вже є великими, залишаються великими. Наступний код є модифікацією коду, який спочатку надав герозавр.

# 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.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.