14

我有数字,需要添加后缀:'st','nd','rd','th'。例如:如果数字是 42 后缀是 'nd' , 521 是 'st' , 113 是 'th' 等等。我需要在 perl 中执行此操作。任何指针。

4

5 回答 5

27

使用Lingua::EN::Numbers::Ordinate。来自简介:

use Lingua::EN::Numbers::Ordinate;
print ordinate(4), "\n";
 # prints 4th
print ordinate(-342), "\n";
 # prints -342nd

# Example of actual use:
...
for(my $i = 0; $i < @records; $i++) {
  unless(is_valid($record[$i]) {
    warn "The ", ordinate($i), " record is invalid!\n"; 
    next;
  }
  ...
}
于 2012-07-06T21:35:38.877 回答
16

试试这个:

my $ordinal;
if ($foo =~ /(?<!1)1$/) {
    $ordinal = 'st';
} elsif ($foo =~ /(?<!1)2$/) {
    $ordinal = 'nd';
} elsif ($foo =~ /(?<!1)3$/) {
    $ordinal = 'rd';
} else {
    $ordinal = 'th';
}
于 2012-07-06T21:35:00.987 回答
7

试试这个简短的子程序

use strict;
use warnings;

sub ordinal {
  return $_.(qw/th st nd rd/)[/(?<!1)([123])$/ ? $1 : 0] for int shift;
}

for (42, 521, 113) {
  print ordinal($_), "\n";
}

输出

42nd
521st
113th
于 2012-07-06T22:04:24.240 回答
3

这是我最初为代码高尔夫挑战编写的解决方案,稍微重写以符合非高尔夫代码的通常最佳实践:

$number =~ s/(1?\d)$/$1 . ((qw'th st nd rd')[$1] || 'th')/e;

它的工作方式是正则表达式(1?\d)$匹配数字的最后一位,如果是,则加上前面的数字1。然后,替换使用匹配的数字作为 list 的索引(qw'th st nd rd'),将 0 映射到th1 到st2 到nd3 到rd以及任何其他值到 undef。最后,||运算符将 undef 替换为th.

如果您不喜欢s///e,基本上可以编写相同的解决方案,例如:

for ($number) {
    /(1?\d)$/ or next;
    $_ .= (qw'th st nd rd')[$1] || 'th';
}

或作为一个函数:

sub ordinal ($) {
    $_[0] =~ /(1?\d)$/ or return;
    return $_[0] . ((qw'th st nd rd')[$1] || 'th');
}
于 2012-07-25T00:30:20.417 回答
1

另一种解决方案(尽管我更喜欢独立于使用模块的预先存在的答案):

use Date::Calc 'English_Ordinal';
print English_Ordinal $ARGV[0];
于 2015-10-16T20:07:11.943 回答