Titelbeschreibung einer Zeichenfolge mit Ausnahmen

86

Gibt es in Python ein Standard - Weg , um eine Zeichenfolge Titlecase (dh Wörter beginnen mit Großbuchstaben, alle verbleibenden verrohrten Zeichen Klein haben) , aber verlassen Artikel wie and, inund ofklein geschrieben?

Yassin
quelle

Antworten:

149

Es gibt ein paar Probleme damit. Wenn Sie Split und Join verwenden, werden einige Leerzeichen ignoriert. Die integrierten Großschreibungs- und Titelmethoden ignorieren Leerzeichen nicht.

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

Wenn ein Satz mit einem Artikel beginnt, möchten Sie nicht das erste Wort eines Titels in Kleinbuchstaben.

Beachten Sie Folgendes:

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
Dheerosaurier
quelle
Warum ist renotwendig? Es gibt eine "".splitFunktion, die dasselbe tut.
wizzwizz4
1
@ wizzwizz4: str.splitBerücksichtigt keine zusammenhängenden Leerzeichen. re.splitbehält Leerzeichen. Diese Funktion verbraucht also keine Leerzeichen.
Dheerosaurier
@dheerosaur Ich dachte, das "".split()hat sie nicht berücksichtigt, aber "".split(" ")getan.
wizzwizz4
Ihr Snippet funktioniert für den title_except('a whim of aN elephant', articles)Fall nicht richtig . Sie können die word.lower() in exceptionsFilterbedingung verwenden, um das Problem zu beheben.
Dariusz Walczak
@dheerosaur Ich suche nach einer Möglichkeit, jedes Wort groß zu schreiben, das nicht nur einem Artikel, sondern auch einer Zahl folgt. Könnten Sie Ihre Antwort ergänzen, um dies zu demonstrieren? ZB 2001 a Space Odysseysollte zurückkehren 2001 A Space Odyssey, wo das agroß geschrieben wird, da es einer Zahl folgt. Danke im Voraus.
ProGrammer
52

Verwenden Sie das Modul titlecase.py ! Funktioniert nur für Englisch.

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

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

Etienne
quelle
1
Das titlecase-Modul funktioniert nicht, wenn die zu konvertierende Zeichenfolge irgendwo eine Zahl enthält.
Troy
1
@Troy es scheint, dass das Nummernproblem behoben ist, oder ich habe Ihren Randfall nicht getroffen. Beispiel: Titelkoffer ('eins 4 zwei') -> 'Eins 4 Zwei'. Jetzt titlecase ('1one') -> '1one', aber '1one'.title () ->' 1One '. obwohl dieser spätere Fall ein Randfall ist und ich nicht sicher bin, ob '1One' der richtige Titel ist. Ich bin auch nicht besorgt genug, um mein Grammatikbuch zu greifen.
brent.payne
Funktioniert nicht bei "321 A BROADWAY STREET", wo ich "321 a Broadway Street" bekomme. Die Verwendung der oben von Dheerosaurier vorgeschlagenen Lösung ergibt "321 A Broadway Street".
MoreScratch
Auch schön, es lässt Akronyme im Titel unberührt. "Entwicklung von innovativem TIaSR" wird zu "Entwicklung von innovativem TIaSR".
Matthias Arras
21

Es gibt folgende Methoden:

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

Es gibt keine Option für Kleinbuchstaben. Sie müssten das selbst codieren, wahrscheinlich mithilfe einer Liste von Artikeln, die Sie senken möchten.

nosklo
quelle
titlecase.py Kleinbuchstaben.
TRS-80
13

Stuart Colville hat eine Python - Port hergestellt von einem Perl - Skript geschrieben von John Gruber zu konvertieren Strings in Titel Fall aber vermeidet Kapitalisierung kleine Worte basierend auf Regeln aus der New York Times Manual of Style, sowie Catering für mehrere Sonderfälle.

Einige der Klugheit dieser Skripte:

  • Sie schreiben kleine Wörter wie if, in, of, on usw. groß, werden jedoch nicht groß geschrieben, wenn sie in der Eingabe fälschlicherweise groß geschrieben werden.

  • In den Skripten wird davon ausgegangen, dass Wörter mit anderen Großbuchstaben als dem ersten Zeichen bereits korrekt großgeschrieben sind. Dies bedeutet, dass sie ein Wort wie "iTunes" in Ruhe lassen, anstatt es in "ITunes" oder, schlimmer noch, in "Itunes" zu zerlegen.

  • Sie überspringen alle Wörter mit Linienpunkten. "Example.com" und "del.icio.us" bleiben in Kleinbuchstaben.

  • Sie haben fest codierte Hacks, die speziell für ungewöhnliche Fälle wie „AT & T“ und „Q & A“ entwickelt wurden. Beide enthalten kleine Wörter (at und a), die normalerweise in Kleinbuchstaben geschrieben werden sollten.

  • Das erste und das letzte Wort des Titels werden immer groß geschrieben, sodass Eingaben wie „Nichts, vor dem man Angst haben muss“ in „Nichts, vor dem man Angst haben muss“ umgewandelt werden.

  • Ein kleines Wort nach einem Doppelpunkt wird großgeschrieben.

Sie können es hier herunterladen .

BioGeek
quelle
4
capitalize (word)

Das sollte reichen. Ich verstehe es anders.

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

Ok, wie in der obigen Antwort gesagt, müssen Sie eine benutzerdefinierte Großschreibung vornehmen:

mytext = u'i bin ein 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)   

Dies gibt aus

I am a Foobar Bazbar
pyfunc
quelle
Das will ich nicht. Ich möchte "Ich bin ein Foobar Bazbar"
Yassin
@ Yassin Ezbakhe: Meine Antwort bearbeitet, das sollte für dich funktionieren. Die Liste der Artikel kann leicht aus jedem Wörterbuch entfernt werden
pyfunc
2

Die Titelmethode von Python 2.7 weist einen Fehler auf.

value.title()

‚kehrt Carpenter S - Assistent wenn der Wert Carpenter‘ s - Assistent

Die beste Lösung ist wahrscheinlich die von @BioGeek mit dem Titel von Stuart Colville. Welches ist die gleiche Lösung von @Etienne vorgeschlagen.

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

Der Titel beginnt mit einem großgeschriebenen Wort und das passt nicht zum Artikel.

Tony Veijalainen
quelle
1

Einzeiler mit Listenverständnis und ternärem Operator

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)

Nervenzusammenbruch:

for word in "Wow, a python one liner for titles".split(" ") Teilt die Zeichenfolge in eine Liste auf und initiiert eine for-Schleife (im Listenverständnis)

word.title() if word not in "the a on in of an" else wordverwendet die native Methode, title()um die Zeichenfolge mit einem Groß- und Kleinschreibung zu versehen, wenn es sich nicht um einen Artikel handelt

" ".join verbindet die Listenelemente mit einem Trennzeichen von (Leerzeichen)

user7297223
quelle
0

Ein wichtiger Fall, der nicht berücksichtigt wird, sind Akronyme (die Python-Titlecase-Lösung kann Akronyme verarbeiten, wenn Sie sie ausdrücklich als Ausnahmen angeben). Ich ziehe es stattdessen vor, einfach ein Fallgehäuse zu vermeiden. Bei diesem Ansatz bleiben Akronyme, die bereits in Großbuchstaben geschrieben sind, in Großbuchstaben. Der folgende Code ist eine Modifikation des ursprünglich von Dheerosaurier bereitgestellten Codes.

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

Beim Ausführen wird Folgendes erzeugt:

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.
August West
quelle