wake-up-neo.com

Ordnungsnummern ersetzen

Ich suche derzeit nach dem Weg, Wörter wie die erste, zweite, dritte, ... mit entsprechender Ordnungszahl (1., 2., 3.) zu ersetzen ... Ich habe in der letzten Woche gegoogelt und habe nichts gefunden jedes nützliche Standardwerkzeug oder jede Funktion von NLTK.

Gibt es irgendwelche oder sollte ich einige reguläre Ausdrücke manuell schreiben?

Danke für jeden Rat

36
skornos

Hier ist eine knappe Lösung aus Gareth auf Codegolf :

ordinal = lambda n: "%d%s" % (n,"tsnrhtdd"[(n/10%10!=1)*(n%10<4)*n%10::4])

Funktioniert mit einer beliebigen Anzahl:

print [ordinal(n) for n in range(1,32)]

['1st', '2nd', '3rd', '4th', '5th', '6th', '7th', '8th', '9th', '10th', '11th',
'12th', '13th', '14th', '15th', '16th', '17th', '18th', '19th', '20th', '21st',
'22nd', '23rd', '24th', '25th', '26th', '27th', '28th', '29th', '30th', '31st']

Für Python 3.4+ wird math.floor benötigt:

import math
ordinal = lambda n: "%d%s" % (n,"tsnrhtdd"[(math.floor(n/10)%10!=1)*(n%10<4)*n%10::4])
83
Ben Davis

Wie wäre es damit:

suf = lambda n: "%d%s"%(n,{1:"st",2:"nd",3:"rd"}.get(n if n<20 else n%10,"th"))
print [suf(n) for n in xrange(1,32)]

['1st', '2nd', '3rd', '4th', '5th', '6th', '7th', '8th', '9th', '10th',
 '11th', '12th', '13th', '14th', '15th', '16th', '17th', '18th', '19th',
 '20th', '21st', '22nd', '23rd', '24th', '25th', '26th', '27th', '28th',
 '29th', '30th', '31st']
8
evandrix

Die akzeptierte Antwort auf eine vorhergehende Frage hat einen Algorithmus für die Hälfte davon: Es "first" wird in 1. Um von dort zu "1st" zu gelangen, führen Sie Folgendes aus:

suffixes = ["th", "st", "nd", "rd", ] + ["th"] * 16
suffixed_num = str(num) + suffixes[num % 100]

Dies funktioniert nur für die Nummern 0-19.

7
lvc

Ich wollte Ordinalzahlen für ein Projekt von mir verwenden und nach einigen Prototypen glaube ich, dass diese Methode zwar nicht für jede positive ganze Zahl geeignet ist, ja jede ganze Zahl .

Es funktioniert durch Festlegen, ob die Zahl über oder unter 20 liegt. Wenn die Zahl unter 20 liegt, wird das int 1 in die Zeichenfolge 1, 2, 2 umgewandelt. 3, 3.; und dem Rest wird "st" hinzugefügt. 

Für Zahlen über 20 werden die letzten und vorletzten Ziffern benötigt, die ich als Zehner bzw. Einheit bezeichnet habe, und sie testen, um zu sehen, was der Zahl hinzugefügt werden soll. 

Dies ist übrigens in Python, also bin ich mir nicht sicher, ob andere Sprachen die vorletzte oder vorletzte Stelle einer Zeichenfolge finden können, wenn sie es recht einfach übersetzen sollte.

def o(numb):
    if numb < 20: #determining suffix for < 20
        if numb == 1: 
            suffix = 'st'
        Elif numb == 2:
            suffix = 'nd'
        Elif numb == 3:
            suffix = 'rd'
        else:
            suffix = 'th'  
    else:   #determining suffix for > 20
        tens = str(numb)
        tens = tens[-2]
        unit = str(numb)
        unit = unit[-1]
        if tens == "1":
           suffix = "th"
        else:
            if unit == "1": 
                suffix = 'st'
            Elif unit == "2":
                suffix = 'nd'
            Elif unit == "3":
                suffix = 'rd'
            else:
                suffix = 'th'
    return str(numb)+ suffix

Ich habe die Funktion "o" zur Vereinfachung der Verwendung aufgerufen und kann durch Importieren des Dateinamens, den ich "ordinal" nannte, importiert werden, indem ordinal dann ordinal.o (number) importiert wird.

Lass mich wissen, was du denkst: D

6
Houngan

Ich tat etwas Ähnliches und musste Adressen mit Ordnungszahlen ('Third St') in ein Format konvertieren, das ein Geocoder ('3rd St') verstehen konnte. Dies ist zwar nicht sehr elegant, aber eine schnelle und schmutzige Lösung ist die Verwendung von inflect.py , um ein Wörterbuch für die Übersetzung zu erstellen. 

inflect.py hat eine number_to_words()-Funktion, die eine Zahl (z. B. 2) in ihre Word-Form (z. B. 'two') umwandelt. Außerdem gibt es eine ordinal()-Funktion, die eine beliebige Zahl (Zahl oder Word-Form) annehmen und in ihre Ordinalform umwandeln kann (z. B. 4 -> fourth, six -> sixth). Keines von ihnen tut das, wonach Sie suchen, aber zusammen können Sie ein Wörterbuch generieren, um jedes gelieferte Ordnungszahl-Wort (innerhalb eines angemessenen Bereichs) in seine entsprechende Ordnungszahl zu übersetzen. Schau mal:

>>> import inflect
>>> p = inflect.engine()
>>> Word_to_number_mapping = {}
>>>
>>> for i in range(1, 100):
...     Word_form = p.number_to_words(i)  # 1 -> 'one'
...     ordinal_Word = p.ordinal(Word_form)  # 'one' -> 'first'
...     ordinal_number = p.ordinal(i)  # 1 -> '1st'
...     Word_to_number_mapping[ordinal_Word] = ordinal_number  # 'first': '1st'
...
>>> print Word_to_number_mapping['sixth']
6th
>>> print Word_to_number_mapping['eleventh']
11th
>>> print Word_to_number_mapping['forty-third']
43rd

Wenn Sie bereit sind, einige Zeit festzuschreiben, ist es möglicherweise möglich, die Funktionsweise von inflect.py in beiden Funktionen zu untersuchen und Ihren eigenen Code zu erstellen, um dies dynamisch zu tun (ich habe nicht versucht, dies zu tun).

6
alukach

Wenn Sie keine zusätzliche Abhängigkeit von einer externen Bibliothek (wie vorgeschlagen von luckydonald ) herstellen möchten, möchten Sie auch nicht, dass der zukünftige Verwalter des Codes Sie verfolgt und Sie (weil Sie) tötet Golfed Code in der Produktion verwendet), dann hier eine kurze, aber wartbare Variante:

def make_ordinal(n):
    '''
    Convert an integer into its ordinal representation::

        make_ordinal(0)   => '0th'
        make_ordinal(3)   => '3rd'
        make_ordinal(122) => '122nd'
        make_ordinal(213) => '213th'
    '''
    n = int(n)
    suffix = ['th', 'st', 'nd', 'rd', 'th'][min(n % 10, 4)]
    if 11 <= (n % 100) <= 13:
        suffix = 'th'
    return str(n) + suffix
4
Florian Brucker

Eine andere Lösung ist die num2words-Bibliothek ( pip | github ) ..__, die insbesondere verschiedene Sprachen anbietet, sodass die Lokalisierung/Internationalisierung (auch bekannt als l10n/i18n) kein Kinderspiel ist.

Die Verwendung ist nach der Installation mit pip install num2words einfach:

from num2words import num2words
# english is default
num2words(4458, to="ordinal_num")
'4458rd'

# examples for other languages
num2words(4458, lang="en", to="ordinal_num")
'4458rd'

num2words(4458, lang="es", to="ordinal_num")
'4458º'

num2words(4458, lang="de", to="ordinal_num")
'4458.'

num2words(4458, lang="id", to="ordinal_num")
'ke-4458'

Bonus:

num2words(4458, lang="en", to="ordinal")
'four thousand, four hundred and fifty-eighth'
3
luckydonald

Versuche dies 

import sys

a = int(sys.argv[1])

for i in range(1,a+1):

j = i
if(j%100 == 11 or j%100 == 12 or j%100 == 13):
    print("%dth Hello"%(j))
    continue            
i %= 10
if ((j%10 == 1) and ((i%10 != 0) or (i%10 != 1))):
    print("%dst Hello"%(j))
Elif ((j%10 == 2) and ((i%10 != 0) or (i%10 != 1))):
    print("%dnd Hello"%(j))
Elif ((j%10 == 3) and ((i%10 != 0) or (i%10 != 1))):
    print("%drd Hello"%(j))
else:
    print("%dth Hello"%(j))
1

Dies ist eine alternative Option, die das Paket num2words verwendet.

>>> from num2words import num2words
>>> num2words(42, to='ordinal_num')
    '42nd'
1
Klahnen

Wenn Sie kein externes Modul importieren möchten und eine einzeilige Lösung bevorzugen, ist das Folgende wahrscheinlich (etwas) lesbarer als die akzeptierte Antwort:

def suffix(i):
    return {1:"st", 2:"nd", 3:"rd"}.get(i%10*(i%100 not in [11,12,13]), "th"))

Es verwendet das Wörterbuch .get, wie von https://codereview.stackexchange.com/a/41300/90593 und https://stackoverflow.com/a/36977549/5069869 vorgeschlagen.

Ich habe die Multiplikation mit einem Boolean verwendet, um die Sonderfälle (11,12,13) ​​zu behandeln, ohne einen If-Block starten zu müssen. Wenn die Bedingung (i%100 not in [11,12,13]) zu False ausgewertet wird, ist die ganze Zahl 0 und wir erhalten den Standardfall 'th'.

1
TheEspinosa

Wenn Sie Django verwenden, können Sie Folgendes tun:

from Django.contrib.humanize.templatetags.humanize import ordinal
var = ordinal(number)

(oder verwenden Sie die Ordinalzahl in einer Django-Vorlage als Vorlagenfilter, der beabsichtigt war, obwohl der Aufruf von Python-Code auch so ist

Wenn Sie nicht Django verwenden, könnten Sie deren Implementierung stehlen, was sehr ordentlich ist.

1
Monika Sulik

Dies kann eine beliebige Länge, die Ausnahmen für ... # 11 bis ... # 13 und negative ganze Zahlen verarbeiten.

def ith(i):return(('th'*(10<(abs(i)%100)<14))+['st','nd','rd',*['th']*7][(abs(i)-1)%10])[0:2]

Ich schlage vor, ith () als Namen zu verwenden, um das eingebaute ord () nicht zu überschreiben.

# test routine
for i in range(-200,200):
    print(i,ith(i))

Hinweis: Getestet mit Python 3.6; Die Funktion abs () war verfügbar, ohne explizit ein Mathematikmodul einzuschließen.

1
Amp Balfour

diese Funktion funktioniert gut für jede Zahl n . Wenn n negativ ist, wird es in positiv umgewandelt. Wenn n keine Ganzzahl ist, wird sie in Ganzzahl konvertiert. 

def ordinal( n ):

    suffix = ['th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th']

    if n < 0:
        n *= -1

    n = int(n)

    if n % 100 in (11,12,13):
        s = 'th'
    else:
        s = suffix[n % 10]

    return str(n) + s
1
Dario Z.

Hier ist eine kompliziertere Lösung, die ich gerade geschrieben habe und die zusammengesetzte Ordinalzahlen berücksichtigt. Es funktioniert also von first bis zu nine hundred and ninety ninth. Ich brauchte es, um String-Straßennamen in die Ordnungszahlen umzuwandeln:

import re
from collections import OrderedDict

ONETHS = {
    'first': '1ST', 'second': '2ND', 'third': '3RD', 'fourth': '4TH', 'fifth': '5TH', 'sixth': '6TH', 'seventh': '7TH',
    'eighth': '8TH', 'ninth': '9TH'
}

TEENTHS = {
    'tenth': '10TH', 'eleventh': '11TH', 'twelfth': '12TH', 'thirteenth': '13TH',
    'fourteenth': '14TH', 'fifteenth': '15TH', 'sixteenth': '16TH', 'seventeenth': '17TH', 'eighteenth': '18TH',
    'nineteenth': '19TH'
}

TENTHS = {
    'twentieth': '20TH', 'thirtieth': '30TH', 'fortieth': '40TH', 'fiftieth': '50TH', 'sixtieth': '60TH',
    'seventieth': '70TH', 'eightieth': '80TH', 'ninetieth': '90TH',
}

HUNDREDTH = {'hundredth': '100TH'}  # HUNDREDTH not s

ONES = {'one': '1', 'two': '2', 'three': '3', 'four': '4', 'five': '5', 'six': '6', 'seven': '7', 'eight': '8',
        'nine': '9'}

TENS = {'twenty': '20', 'thirty': '30', 'forty': '40', 'fifty': '50', 'sixty': '60', 'seventy': '70', 'eighty': '80',
        'ninety': '90'}

HUNDRED = {'hundred': '100'}

# Used below for ALL_ORDINALS
ALL_THS = {}
ALL_THS.update(ONETHS)
ALL_THS.update(TEENTHS)
ALL_THS.update(TENTHS)
ALL_THS.update(HUNDREDTH)

ALL_ORDINALS = OrderedDict()
ALL_ORDINALS.update(ALL_THS)
ALL_ORDINALS.update(TENS)
ALL_ORDINALS.update(HUNDRED)
ALL_ORDINALS.update(ONES)


def split_ordinal_Word(word):
    ordinals = []
    if not Word:
        return ordinals 

    for key, value in ALL_ORDINALS.items():
        if Word.startswith(key):
            ordinals.append(key)
            ordinals += split_ordinal_Word(word[len(key):])
            break
    return ordinals

def get_ordinals(s):
    ordinals, start, end = [], [], []
    s = s.strip().replace('-', ' ').replace('and', '').lower()
    s = re.sub(' +',' ', s)  # Replace multiple spaces with a single space
    s = s.split(' ')

    for Word in s:
        found_ordinals = split_ordinal_Word(word)
        if found_ordinals:
            ordinals += found_ordinals
        else:  # else if Word, for covering blanks
            if ordinals:  # Already have some ordinals
                end.append(Word)
            else:
                start.append(Word)
    return start, ordinals, end


def detect_ordinal_pattern(ordinals):
    ordinal_length = len(ordinals)
    ordinal_string = '' # ' '.join(ordinals)
    if ordinal_length == 1:
        ordinal_string = ALL_ORDINALS[ordinals[0]]
    Elif ordinal_length == 2:
        if ordinals[0] in ONES.keys() and ordinals[1] in HUNDREDTH.keys():
            ordinal_string = ONES[ordinals[0]] + '00TH'
        Elif ordinals[0] in HUNDRED.keys() and ordinals[1] in ONETHS.keys():
            ordinal_string = HUNDRED[ordinals[0]][:-1] + ONETHS[ordinals[1]]
        Elif ordinals[0] in TENS.keys() and ordinals[1] in ONETHS.keys():
            ordinal_string = TENS[ordinals[0]][0] + ONETHS[ordinals[1]]
    Elif ordinal_length == 3:
        if ordinals[0] in HUNDRED.keys() and ordinals[1] in TENS.keys() and ordinals[2] in ONETHS.keys():
            ordinal_string = HUNDRED[ordinals[0]][0] + TENS[ordinals[1]][0] + ONETHS[ordinals[2]]
        Elif ordinals[0] in ONES.keys() and ordinals[1] in HUNDRED.keys() and ordinals[2] in ALL_THS.keys():
            ordinal_string =  ONES[ordinals[0]] + ALL_THS[ordinals[2]]
    Elif ordinal_length == 4:
        if ordinals[0] in ONES.keys() and ordinals[1] in HUNDRED.keys() and ordinals[2] in TENS.keys() and \
           ordinals[3] in ONETHS.keys():
                ordinal_string = ONES[ordinals[0]] + TENS[ordinals[2]][0] + ONETHS[ordinals[3]]

    return ordinal_string

Und hier ein paar Beispiele:

# s = '32 one   hundred and forty-third st toronto, on'
#s = '32 forty-third st toronto, on'
#s = '32 one-hundredth st toronto, on'
#s = '32 hundred and third st toronto, on'
#s = '32 hundred and thirty first st toronto, on'
# s = '32 nine hundred and twenty third st toronto, on'
#s = '32 nine hundred and ninety ninth st toronto, on'
s = '32 sixty sixth toronto, on'

st, ords, en = get_ordinals(s)
print st, detect_ordinal_pattern(ords), en
0
radtek

Gareths Code, ausgedrückt mit dem modernen .format ()

ordinal = lambda n: "{}{}".format(n,"tsnrhtdd"[(n/10%10!=1)*(n%10<4)*n%10::4])
0

Ich grüße Gareths Lambda-Code. So elegant. Ich verstehe nur halb, wie es funktioniert. Also habe ich versucht, es zu dekonstruieren und kam dazu:

def ordinal(integer):

    int_to_string = str(integer)

    if int_to_string == '1' or int_to_string == '-1':
        print int_to_string+'st'
        return int_to_string+'st';
    Elif int_to_string == '2' or int_to_string == '-2':
        print int_to_string+'nd'
        return int_to_string+'nd';
    Elif int_to_string == '3' or int_to_string == '-3':
        print int_to_string+'rd'
        return int_to_string+'rd';

    Elif int_to_string[-1] == '1' and int_to_string[-2] != '1':
        print int_to_string+'st'
        return int_to_string+'st';
    Elif int_to_string[-1] == '2' and int_to_string[-2] != '1':
        print int_to_string+'nd'
        return int_to_string+'nd';
    Elif int_to_string[-1] == '3' and int_to_string[-2] != '1':
        print int_to_string+'rd'
        return int_to_string+'rd';

    else:
        print int_to_string+'th'
        return int_to_string+'th';


>>> print [ordinal(n) for n in range(1,25)]
1st
2nd
3rd
4th
5th
6th
7th
8th
9th
10th
11th
12th
13th
14th
15th
16th
17th
18th
19th
20th
21st
22nd
23rd
24th
['1st', '2nd', '3rd', '4th', '5th', '6th', '7th', '8th', '9th', '10th',             
'11th', '12th', '13th', '14th', '15th', '16th', '17th', '18th', '19th', 
'20th', '21st', '22nd', '23rd', '24th']
0

Es gibt eine ordinale Funktion in humanize

pip install humanize

>>> [(x, humanize.ordinal(x)) for x in (1, 2, 3, 4, 20, 21, 22, 23, 24, 100, 101,
...                                     102, 103, 113, -1, 0, 1.2, 13.6)]
[(1, '1st'), (2, '2nd'), (3, '3rd'), (4, '4th'), (20, '20th'), (21, '21st'),
 (22, '22nd'), (23, '23rd'), (24, '24th'), (100, '100th'), (101, '101st'),
 (102, '102nd'), (103, '103rd'), (113, '113th'), (-1, '-1th'), (0, '0th'),
 (1.2, '1st'), (13.6, '13th')]

0
timdiels