我目前正在寻找一种方法,用适当的序数表示法(1st, 2nd, 3rd)替换像first、second、third这样的单词。
我已经谷歌了一个星期,没有发现任何有用的标准工具或来自NLTK的任何函数。
所以是否有任何工具可用,还是我应该手动编写一些正则表达式呢?
感谢任何建议。
包number-parser可以将序数词(例如“first”,“second”等)解析为整数。
from number_parser import parse_ordinal
n = parse_ordinal("first")
要将整数转换为“1st”、“2nd”等形式,可以使用以下代码:
def ordinal(n: int):
if 11 <= (n % 100) <= 13:
suffix = 'th'
else:
suffix = ['th', 'st', 'nd', 'rd', 'th'][min(n % 10, 4)]
return str(n) + suffix
以下是更加精简但不太易读的版本(摘自codegolf上的Gareth回答):
ordinal = lambda n: "%d%s" % (n,"tsnrhtdd"[(n//10%10!=1)*(n%10<4)*n%10::4])
这适用于任何数字:
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']
n/10
需要使用整数除法 /
,这在 Python 2 和 3 之间有所改变。 - Sp3000如果您不想引入外部库的其他依赖项(如luckydonald建议的),但也不希望未来代码维护者追杀并杀死您(因为您在生产中使用了golfed code),那么这里有一个简短但易于维护的变体:
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)
if 11 <= (n % 100) <= 13:
suffix = 'th'
else:
suffix = ['th', 'st', 'nd', 'rd', 'th'][min(n % 10, 4)]
return str(n) + suffix
lambda n: "".join([str(n), ['th', 'st', 'nd', 'rd', 'th'][min(n % 10, 4)] if not 11 <= n <= 13 else "th"])
例如:dt_tr_fn = lambda n: "".join([str(n), ['th', 'st', 'nd', 'rd', 'th'][min(n % 10, 4)] if not 11 <= n <= 13 else "th"])
[dt for dt in map(dt_tr_fn, range(1,32))]
@ye-lin-aung - Doogle11 <= (n % 100) <= 13
而不是只有 n
,否则它将无法通过,例如 112
。 - Florian Brucker这个怎么样:
suf = lambda n: "%d%s"%(n,{1:"st",2:"nd",3:"rd"}.get(n%100 if (n%100)<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']
n%100 < 20
就可以了,对吧?"%d%s"%(n,{1:"st",2:"nd",3:"rd"}.get(n if (n % 100)<20 else n%10,"th"))
- Sreenikethan I'first'
→ '1st'
),而是提出了另一个问题(1
→ '1st'
)。 - törzsmókusnum2words
库。它特别提供了不同的语言,因此本地化/国际化(也称为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'
奖励:
num2words(4458, lang="en", to="ordinal")
'four thousand, four hundred and fifty-eighth'
from number_parser import parse_ordinal
parse_ordinal("twenty third")
23
请注意,此时此刻它仅支持英语、印地语、西班牙语、乌克兰语和俄语。
'first'
→ '1st'
),而是解决另一个问题(1
→ '1st'
)。 - törzsmókus之前的问题的被采纳答案提供了一种算法,可以将"first"
转换为1
。要从这里转换为"1st"
,可以进行如下操作:
suffixes = ["th", "st", "nd", "rd", ] + ["th"] * 16
suffixed_num = str(num) + suffixes[num % 100]
这仅适用于0-19的数字。
{'first': '1st'}
等来避免使用 suffixes
列表。 - lvc'first'
→ '1st'
),而是提出了另一个问题(1
→'1st'
)。 - törzsmókusnumber_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
'first'
→ '1st'
),而是提出了另一个问题(1
→'1st'
)。 - törzsmókus我想在我的一个项目中使用序数词,在尝试了几个原型之后,我认为这种方法虽然不小,但适用于任何正整数,是的任何整数。
它的工作原理是确定数字是大于还是小于20,如果数字小于20,它将把int 1转换为字符串1st,2转换为2nd;3转换为3rd;其余的数字后面加上"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
如果使用Django,您可以执行以下操作:
from django.contrib.humanize.templatetags.humanize import ordinal
var = ordinal(number)
如果您使用Django模板,可以使用序数作为模板过滤器,尽管从Python代码中这样调用也可以。
如果不使用Django,您可以借鉴他们的实现,非常整洁。
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')]
'first'
→ '1st'
),而是提出了另一个问题(1
→ '1st'
)。 - törzsmókus这个函数适用于每个数字n。如果n是负数,它将被转换为正数。如果n不是整数,它将被转换为整数。
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
'first'
→ '1st'
),而是解决了另一个问题(1
→ '1st'
)。 - törzsmókus
pyparsing
这样的工具会让它变得更容易! - Katriel'first'
→'1st'
),而是另一个问题(1
→1st
)。 - törzsmókus