我有一个整数列表 - 是否有一个库可以将它们转换为纯文本排名?IE: 1,2,3 -> “第一,第二,第三”?
7 回答
pythoninflect
包有一个将数字转换为序数的方法:
import inflect
p = inflect.engine()
for i in range(1,25,5):
print(p.ordinal(i))
显示:
1st
6th
11th
16th
21st
你打算去多高?(你有没有期望高于,比如说,“二十”?)
也许你只需要一个dict
,
nth = {
1: "first",
2: "second",
3: "third",
4: "fourth"
# etc
}
由于要点,无法评论 ryvantage 的帖子,但我为 python 编写了相同的代码:
def appendInt(num):
if num > 9:
secondToLastDigit = str(num)[-2]
if secondToLastDigit == '1':
return 'th'
lastDigit = num % 10
if (lastDigit == 1):
return 'st'
elif (lastDigit == 2):
return 'nd'
elif (lastDigit == 3):
return 'rd'
else:
return 'th'
def appendInt2(num):
value = str(num)
if len(value) > 1:
secondToLastDigit = value[-2]
if secondToLastDigit == '1':
return 'th'
lastDigit = value[-1]
if (lastDigit == '1'):
return 'st'
elif (lastDigit == '2'):
return 'nd'
elif (lastDigit == '3'):
return 'rd'
else:
return 'th'
第二个更像是直接翻译,但我发现第一个变体要快得多:
2015 年 8 月 28 日星期五 11:48:13 结果
300000005 function calls in 151.561 seconds
Ordered by: call count, name/file/line
ncalls tottime percall cumtime percall filename:lineno(function)
100000000 6.674 0.000 6.674 0.000 {len}
100000000 43.064 0.000 43.064 0.000 test.py:7(appendInt)
100000000 66.664 0.000 73.339 0.000 test.py:22(appendInt2)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 151.561 151.561 <string>:1(<module>)
1 0.000 0.000 151.561 151.561 test.py:51(main)
1 16.737 16.737 59.801 59.801 test.py:39(test1)
1 18.421 18.421 91.759 91.759 test.py:45(test2)
与@ Hugh Bothwell 所遵循的脉络类似,只是不使用 a dict
(因为您的键已经很好并且是数字的),我将以下“一个衬里”放在一起:
ordinal=lambda x:["first","second","third","fourth","fifth","sixth","seventh","eighth","ninth","tenth","eleventh","twelfth"][x-1]
它涵盖了最多 12 个的所有情况。如果您需要更高(到数百个等),那么您可能需要更健壮的东西(我想像递归等)。
根据您的情况,您可能会发现保留整数并附加“st”、“nd”、“rd”和“th”很有用。如果是这样,这是一个简单的算法:
注意:此算法是用 Java 编写的。我不知道Python。任何想用 Python 重写它的人,请成为我的客人。
public static String appendInt(int number) {
String value = String.valueOf(number);
if(value.length() > 1) {
// Check for special case: 11 - 13 are all "th".
// So if the second to last digit is 1, it is "th".
char secondToLastDigit = value.charAt(value.length()-2);
if(secondToLastDigit == '1')
return "th";
}
char lastDigit = value.charAt(value.length()-1);
switch(lastDigit) {
case '1':
return "st";
case '2':
return "nd";
case '3':
return "rd";
default:
return "th";
}
}
所以
System.out.println(1 + appendInt(1));
System.out.println(2 + appendInt(2));
System.out.println(3 + appendInt(3));
System.out.println(4 + appendInt(4));
System.out.println(5 + appendInt(5));
System.out.println(11 + appendInt(11));
System.out.println(21 + appendInt(21));
显示
1st
2nd
3rd
4th
5th
11th
21st
一个漂亮而简单的重写:
def num_to_ith(num):
"""1 becomes 1st, 2 becomes 2nd, etc."""
value = str(num)
before_last_digit = value[-2]
last_digit = value[-1]
if len(value) > 1 and before_last_digit == '1': return value +'th'
if last_digit == '1': return value + 'st'
if last_digit == '2': return value + 'nd'
if last_digit == '3': return value + 'rd'
return value + 'th'
我的代码使用列表、整数模数来查找第一个数字和整数下除法来检查规则 11 到 13。
def stringify(number):
suffix = ["th","st","nd","rd","th","th","th","th","th","th"]
return str(number) + suffix[number % 10] if str(number // 10)[-1] != 1 else str(number) + "th"
最后一行更具可读性:
if str(number // 10)[-1] != '1':
return str(number) + suffix[number % 10]
else:
return str(number) + "th"
基本上,我正在检查第二个数字的 1*,这表明可能存在第 11、12、13 个规则破坏者。对于规则保持者,列表由除以 10(模运算符)的其余部分引用。
我没有对代码效率进行任何测试,并且检查长度更具可读性,但这很有效。
*(str(number)[-2] 如果输入是单个数字,则生成 IndexError。对整数使用下除法始终会产生至少 1 位数字,因此字符串将始终具有 -1 索引)