Mam numer i trzeba dodać przyrostek: "st", "nd", "rd", "th". Na przykład: jeśli liczba wynosi 42, sufiksem jest "nd", 521 to "st", a 113 to "th" i tak dalej. Muszę to zrobić w Perlu. Wszelkie wskazówki.Jak pobrać numer porządkowy liczby całkowitej w Perlu (np. St, nd, rd, th)
Odpowiedz
Spróbuj tego:
my $ordinal;
if ($foo =~ /(?<!1)1$/) {
$ordinal = 'st';
} elsif ($foo =~ /(?<!1)2$/) {
$ordinal = 'nd';
} elsif ($foo =~ /(?<!1)3$/) {
$ordinal = 'rd';
} else {
$ordinal = 'th';
}
Korzystając Lingua::EN::Numbers::Ordinate. Z STRESZCZENIE:
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;
}
...
}
Spróbuj krótkie podprogramu
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";
}
wyjście
42nd
521st
113th
Jest coś, czego nie rozumiem tutaj w pełni. Dlaczego pętla 'for', gdy występuje tylko jeden element jako argument? Może również działać 'return int (shift). (qw/... '. Dla wielu parametrów pętla' for' nie działałaby ani z powodu instrukcji 'return', działa dobrze, ale czy tęskniłem za czymś na temat pętli? – Birei
@Birei: po prostu sposób umieszczenia '$ _ [0]' na '$ _'. Twój sposób nie zadziałałby, ponieważ wyrażenie regularne potrzebuje wartości w' $ _' Jest to bardzo podobne do nowego 'danego' języka, ale ty nie można tego używać jako modyfikatora instrukcji, jak to możliwe z 'for' . – Borodin
Ah, ok. Dziękuję.Nie otrzymałem punktu' $ _' .Należy go ** + 1 **. – Birei
Oto rozwiązanie which I originally wrote for a code golf challenge, nieznacznie przepisywane w celu dostosowania do zwykłych najlepszych praktyk dla kodu non-golfa :
$number =~ s/(1?\d)$/$1 . ((qw'th st nd rd')[$1] || 'th')/e;
Sposób działania polega na tym, że wyrażenie regularne (1?\d)$
dopasowuje ostatnią cyfrę numeru plus poprzednią cyfrę, jeśli jest to 1
. Substytucja używa następnie dopasowanych cyfr jako indeksu do listy (qw'th st nd rd')
, odwzorowującej od 0 do th
, od 1 do st
, od 2 do nd
, od 3 do rd
i dowolnej innej wartości do undef. Wreszcie, operator ||
zastępuje undef z th
.
Jeśli nie podoba Ci się s///e
, w zasadzie można napisać to samo rozwiązanie np. tak:
for ($number) {
/(1?\d)$/ or next;
$_ .= (qw'th st nd rd')[$1] || 'th';
}
lub jako funkcja:
sub ordinal ($) {
$_[0] =~ /(1?\d)$/ or return;
return $_[0] . ((qw'th st nd rd')[$1] || 'th');
}
Innym rozwiązaniem (chociaż lubię istniejące wcześniej odpowiedzi, które są niezależne od zastosowania modułów lepiej):
use Date::Calc 'English_Ordinal';
print English_Ordinal $ARGV[0];
upvote do użytku produkcyjnego nieuchwytnego, negatywnego zdania o zerowej szerokości. Chociaż (niestety) jak wskazuje Bill Ruppert, istnieje już moduł CPAN. –
Chociaż * jest * rozwiązaniem CPAN, to też mi się podoba. Jest dobrze przemyślany, czytelny, pozbawiony zależności i tak dokładny jak rozwiązanie CPAN dla dowolnej liczby całkowitej. – DavidO