Ho il numero e devo aggiungere il suffisso: "st", "nd", "rd", "th". Quindi per esempio: se il numero è 42 il suffisso è 'nd', 521 è 'st' e 113 è 'th' e così via. Ho bisogno di farlo in perl. Qualsiasi suggerimento.Come recuperare il suffisso ordinale di un intero in Perl (come st, nd, rd, th)
risposta
Prova questo:
my $ordinal;
if ($foo =~ /(?<!1)1$/) {
$ordinal = 'st';
} elsif ($foo =~ /(?<!1)2$/) {
$ordinal = 'nd';
} elsif ($foo =~ /(?<!1)3$/) {
$ordinal = 'rd';
} else {
$ordinal = 'th';
}
Usa Lingua::EN::Numbers::Ordinate. Dalla sinossi:
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;
}
...
}
Prova questa breve subroutine
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";
}
uscita
42nd
521st
113th
C'è qualcosa che non capisco completamente qui. Perché un ciclo 'for' quando c'è un solo elemento come argomento? Potrebbe anche funzionare 'return int (shift). (qw/... '. Per molti parametri il ciclo' for' non funzionerebbe neanche a causa dell'istruzione 'return'. Funziona bene così com'è, ma mi sono perso qualcosa del ciclo? – Birei
@Birei: è solo un modo di mettere '$ _ [0]' in '$ _'. Il tuo modo non funzionerebbe in quanto l'espressione regolare ha bisogno che il valore sia in' $ _'. È molto simile alla nuova parola di lingua 'given' ma tu non posso usare questo come un modificatore di istruzioni come è possibile con 'for'. – Borodin
Ah, ok Grazie, non ho capito il punto di $ _ _. Merita un ** + 1 **. – Birei
Ecco una soluzione which I originally wrote for a code golf challenge, leggermente riscritto per conformarsi alle consuete buone pratiche per il codice non-golf :
$number =~ s/(1?\d)$/$1 . ((qw'th st nd rd')[$1] || 'th')/e;
Il modo in cui funziona è che l'espressione regolare (1?\d)$
corrisponde all'ultima cifra del numero, più la cifra precedente se è 1
. La sostituzione utilizza quindi la (e) cifra (e) corrispondente come indice alla lista (qw'th st nd rd')
, mappando da 0 a , da 1 a , da 3 a rd
e qualsiasi altro valore a undef. Infine, l'operatore ||
sostituisce undef con th
.
Se non ti piace s///e
, in sostanza la soluzione potrebbe essere scritta ad es. in questo modo:
for ($number) {
/(1?\d)$/ or next;
$_ .= (qw'th st nd rd')[$1] || 'th';
}
o come una funzione:
sub ordinal ($) {
$_[0] =~ /(1?\d)$/ or return;
return $_[0] . ((qw'th st nd rd')[$1] || 'th');
}
Un'altra soluzione (se mi piace le risposte preesistenti che sono indipendenti di utilizzare moduli migliore):
use Date::Calc 'English_Ordinal';
print English_Ordinal $ARGV[0];
Upvote per uso produttivo dell'affermazione elusiva di look-behind negativa a larghezza zero. Sebbene (purtroppo) come fa notare Bill Ruppert, esiste già un modulo CPAN. –
Anche se ci * è * una soluzione CPAN, mi piace anche questa. È ben congegnato, altamente leggibile, privo di dipendenze e preciso come la soluzione CPAN per qualsiasi intero. – DavidO