序数替换

sko*_*nos 41 python ordinals nlp nltk

我目前正在寻找用适当的序数表示(第1,第2,第3)替换第一,第二,第三等字的方法.我上周一直在谷歌搜索,我没有找到任何有用的标准工具或NLTK的任何功能.

那么有没有或者我应该手动编写一些正则表达式?

谢谢你的建议

Ben*_*vis 95

这是Gareth在codegolf上采用的简洁解决方案:

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

适用于任何数字:

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']
Run Code Online (Sandbox Code Playgroud)

对于python 3.4+,math.floor需要:

import math
ordinal = lambda n: "%d%s" % (n,"tsnrhtdd"[(math.floor(n/10)%10!=1)*(n%10<4)*n%10::4])
Run Code Online (Sandbox Code Playgroud)

  • 可爱,但来吧,这只是丑陋的 (18认同)
  • 你可以在python3中使用//进行整数除法:ordinal = lambda n:"%d%s"%(n,"tsnrhtdd"[(n // 10%10!= 1)*(n%10 <4)*N%10:4]) (14认同)
  • 我正在与使用它的压倒性冲动作斗争。 (6认同)
  • 这似乎不再适用于python3.4,例如ordinal(13)='13rd'.我不知道为什么.str(n)+ {1:'st',2:'nd',3:'rd'}.get(4如果10 <= n%100 <20 else n%10,"th")有效. (3认同)
  • @BrettDiDonato`n/10`要求`/`是整数除法,它在Python 2和3之间改变 (2认同)
  • 使用 f 字符串: `ordinal = lambda n: f'{n}{"tsnrhtdd"[(n//10%10!=1)*(n%10&lt;4)*n%10::4]}' ` (2认同)

eva*_*rix 12

这个怎么样:

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']
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个,更具可读性。但它适用于 n &gt; 100 吗? (4认同)

luc*_*ald 10

另一个解决方案是num2words库(pip | github)。它特别提供了不同的语言,因此本地化/国际化(又名 l10n/i18n)是显而易见的。

安装后使用很容易pip install num2words

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

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

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'
Run Code Online (Sandbox Code Playgroud)

奖金:

num2words(4458, lang="en", to="ordinal")
'four thousand, four hundred and fifty-eighth'
Run Code Online (Sandbox Code Playgroud)


lvc*_*lvc 7

前一个问题的接受答案有一半的算法:它变成"first"1.要从那里去"1st",做一些像:

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

这仅适用于数字0-19.


Hou*_*gan 6

我想在我的项目中使用序数,在几个原型之后,我认为这个方法虽然不小,但对任何正整数都适用,是任何整数.

它通过确定数字是高于还是低于20来工作,如果数字低于20,它将把int 1变成字符串1,2,2; 3,3; 其余的将添加"st".

对于超过20的数字,它将采用最后和倒数第二个数字,我分别称为十位和单位,并测试它们以查看要添加到数字的内容.

顺便说一下,这是python,所以我不确定其他语言是否能够找到字符串的最后一个或倒数第二个数字,如果它们应该很容易翻译.

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
Run Code Online (Sandbox Code Playgroud)

为了便于使用,我调用了函数"o",可以通过import ordinal然后ordinal.o(number)导入我称之为"ordinal"的文件名来调用.

让我知道你的想法:D


alu*_*ach 6

我发现自己做了类似的事情,需要将带序数的地址('Third St')转换为地理编码器可以理解的格式('3rd St').虽然这不是很优雅,但一个快速而肮脏的解决方案是使用inflect.py生成翻译字典.

inflect.py有一个number_to_words()函数,它会将一个数字(例如2)转换成它的单词形式(例如'two').此外,还有一个ordinal()函数可以采用任何数字(数字或单词形式)并将其转换为它的序数形式(例如4- > fourth,six- > sixth).这些都不是他们自己做的,你可以用它们来生成一个字典,将任何提供的序数字(在合理的范围内)翻译成它各自的数字顺序.看一看:

>>> 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
Run Code Online (Sandbox Code Playgroud)

如果您愿意花一些时间,可以检查inflect.py在这两个函数中的内部工作原理并构建自己的代码来动态执行此操作(我没有尝试过这样做).


Mon*_*lik 6

如果使用 django,你可以这样做:

from django.contrib.humanize.templatetags.humanize import ordinal
var = ordinal(number)
Run Code Online (Sandbox Code Playgroud)

(或在 django 模板中使用 ordinal 作为模板过滤器,尽管从 python 代码中这样调用它也可以)

如果不使用 django,你可以窃取他们非常简洁的实现。


Flo*_*ker 5

如果您不想增加对外部库的依赖(如luckydonald建议),但又不想让代码的未来维护者困扰您并杀死您(因为您在生产中使用了经过改进的代码)然后是一个简短但可维护的变体:

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
Run Code Online (Sandbox Code Playgroud)