У меня есть номер, и мне нужно добавить суффикс: «st», «nd», «rd», «th». Так, например: если число равно 42, суффикс будет «nd», 521 — «st», 113 — «th» и так далее. Мне нужно сделать это в Perl. Любые указатели.
Как получить порядковый суффикс целого числа в Perl (например, st, nd, rd, th)
Ответы (5)
Попробуй это:
my $ordinal;
if ($foo =~ /(?<!1)1$/) {
$ordinal = 'st';
} elsif ($foo =~ /(?<!1)2$/) {
$ordinal = 'nd';
} elsif ($foo =~ /(?<!1)3$/) {
$ordinal = 'rd';
} else {
$ordinal = 'th';
}
sub ordinal { my $n = shift; return "${n}st" if $n =~ /(?<!1)1$/; return "${n}nd" if $n =~ /(?<!1)2$/; return "${n}rd" if $n =~ /(?<!1)3$/; return "${n}th"; }
. (Примечание: это также возвращает сам номер)
- person matemaciek; 26.09.2018
Используйте 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;
}
...
}
Попробуйте эту короткую подпрограмму
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
for
, когда в качестве аргумента используется только один элемент? Это также может сработать return int( shift ) . (qw/...
. Для некоторых параметров цикл for
не будет работать ни из-за оператора return
. Он отлично работает как есть, но я что-то пропустил в цикле?
- person Birei; 23.07.2012
$_[0]
в $_
. Ваш способ не сработает, так как регулярное выражение требует, чтобы значение было в $_
. Это очень похоже на новое слово языка given
, но вы не можете использовать его в качестве модификатора оператора, как вы можете использовать с for
.
- person Borodin; 23.07.2012
$_
. Он заслуживает +1.
- person Birei; 23.07.2012
for
это все, что должен делать сломанный given
, но это уже другая история.
- person Borodin; 05.06.2014
Вот решение, которое я изначально написал для игры в гольф, немного переписанное, чтобы соответствовать обычным рекомендациям для кода, не относящегося к гольфу. :
$number =~ s/(1?\d)$/$1 . ((qw'th st nd rd')[$1] || 'th')/e;
Это работает следующим образом: регулярное выражение (1?\d)$
соответствует последней цифре числа плюс предшествующая цифра, если это 1
. Затем подстановка использует совпадающие цифры в качестве индекса для списка (qw'th st nd rd')
, отображая 0 на th
, 1 на st
, 2 на nd
, 3 на 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');
}
Другое решение (хотя мне больше нравятся уже существующие ответы, которые не зависят от использования модулей):
use Date::Calc 'English_Ordinal';
print English_Ordinal $ARGV[0];