Ich habe Nummer und muss das Suffix hinzufügen: 'st', 'nd', 'rd', 'th'. Also zum Beispiel: wenn die Zahl 42 ist, ist das Suffix "nd", 521 ist "st" und 113 ist "th" und so weiter. Ich muss dies in Perl tun. Irgendwelche Zeiger.Wie erhalte ich das Ordinal Suffix einer ganzen Zahl in Perl (wie st, nd, rd, th)
Antwort
Versuchen Sie folgendes:
my $ordinal;
if ($foo =~ /(?<!1)1$/) {
$ordinal = 'st';
} elsif ($foo =~ /(?<!1)2$/) {
$ordinal = 'nd';
} elsif ($foo =~ /(?<!1)3$/) {
$ordinal = 'rd';
} else {
$ordinal = 'th';
}
Verwendung Lingua::EN::Numbers::Ordinate. Aus der Übersicht:
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;
}
...
}
Versuchen Sie, diese kurze Unterprogramm
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";
}
Ausgang
42nd
521st
113th
Es gibt etwas, das ich hier nicht vollständig verstehe. Warum eine 'for'-Schleife, wenn nur ein Element als Argument existiert? Es könnte auch 'return int (shift) funktionieren. (qw/... '. Für einige Parameter würde die 'for'-Schleife nicht funktionieren, auch nicht wegen der' return'-Anweisung. Es funktioniert gut wie es ist, aber habe ich etwas an der Schleife übersehen? – Birei
@Birei: es ist nur eine Möglichkeit, '$ _ [0]' in '$ _' zu setzen.Ihr Weg würde nicht funktionieren, da der reguläre Ausdruck den Wert in' $ _' benötigt.Es ist sehr wie das neue 'gegebene' Sprachwort, aber Sie kann das nicht als Statement-Modifier verwenden, wie du es mit 'for' kannst." – Borodin
Ah, ok. Danke. Hat nicht den Sinn von '$ _'. Es verdient eine ** + 1 **. – Birei
Hier eine Lösung ist which I originally wrote for a code golf challenge, etwas für die Code-nicht-Golf zu üblichen Best Practices entsprechen neu geschrieben :
$number =~ s/(1?\d)$/$1 . ((qw'th st nd rd')[$1] || 'th')/e;
Die Art und Weise, wie es funktioniert, ist, dass die Regexp (1?\d)$
die letzte Ziffer der Nummer übereinstimmt, plus die vorangehende Ziffer, wenn es 1
ist. Die Substitution verwendet dann die übereinstimmenden Ziffern als Index für die Liste (qw'th st nd rd')
, Abbildung 0 bis th
, 1 bis st
, 2 bis nd
, 3 bis rd
und jeden anderen Wert für undef. Schließlich ersetzt der Operator ||
undef durch th
.
Wenn Sie nicht mögen s///e
, könnte im Wesentlichen die gleiche Lösung geschrieben werden, z. dies wie:
for ($number) {
/(1?\d)$/ or next;
$_ .= (qw'th st nd rd')[$1] || 'th';
}
oder als Funktion:
sub ordinal ($) {
$_[0] =~ /(1?\d)$/ or return;
return $_[0] . ((qw'th st nd rd')[$1] || 'th');
}
eine andere Lösung (obwohl ich mag die bereits existierenden Antworten, die einer Verwendung der Module besser unabhängig sind):
use Date::Calc 'English_Ordinal';
print English_Ordinal $ARGV[0];
Upvote für den produktiven Einsatz der schwer zu fassenden Negativ-Look-Behind-Assertion. Obwohl (leider) Bill Ruppert darauf hinweist, gibt es dafür bereits ein CPAN-Modul. –
Obwohl es eine CPAN-Lösung gibt, gefällt mir auch diese. Es ist gut durchdacht, gut lesbar, ohne Abhängigkeiten und so genau wie die CPAN-Lösung für jede ganze Zahl. – DavidO