In un contesto di lista, ordina la LISTA e restituisce
il valore della lista ordinata. In un contesto scalare
il comportamento di sort() è indefinito.
Se NOMESUB o BLOCCO vengono omessi, ordina secondo il
confronto standard tra stringhe. Se NOMESUB viene
specificato, esso fornisce il nome di una subroutine
che restituisce un intero minore, uguale o maggiore di
0 a seconda di come gli elementi della lista devono
essere ordinati. (Gli operatori <=> e cmp sono
estremamente utili in tali routine).
NOMESUB può essere il nome di una variabile
scalare (senza indici di array o chiavi di hash), nel qual
caso il valore fornisce il nome (o un riferimento) della
subroutine che si deve in effetti usare. Al posto di NOMESUB
si può fornire un BLOCCO in qualità
di subroutine anonima, interna.
Se il prototipo della subroutine è ($$),
gli elementi da confrontare sono passati per riferimento
in @_, come accade per una normale subroutine.
Ciò è più lento rispetto ad una subroutine
senza prototipo, dove gli elementi da confrontare sono
passati alla subroutine nelle variabili package globali
$a e $b (guardate l'esempio sottostante). Va notato che
in quest'ultimo caso è tipicamente
controproducente dichiarare $a e $b come lessicali.
In entrambi i casi la subroutine non può essere ricorsiva. I valori da confrontare sono sempre passati per riferimento, quindi non dovrebbero essere modificati.
Inoltre, non potte uscire dal blocco o dalla subroutine
di ordinamento usando uno degli operatori di controllo del
ciclo descritti in perlsyn o con goto.
Quando use locale è attivo, sort LISTA
ordina la lista secondo il riscontro del "locale" corrente.
Consultate perllocale.
sort() restituisce gli alias alla lista originaria, così come una variabile indice del ciclo for restituisce degli alias agli elementi della lista.
Cioè, modificare un elemento di una lista restituita da sort()
(per esempio, in un foreach, map o grep) modifica proprio
l'elemento della lista originare
much as a for loop's index
variable aliases the list elements. That is, modifying an element of a
list returned by sort() (for example, in a foreach, map or grep)
actually modifies the element in the original list. This is usually
something to be avoided when writing clear code.
Perl 5.6 e le versioni precedenti usavano l'algoritmo quicksort per implementare l'ordinamento. Quell'algoritmo non era stabile, e avrebbe potuto avere un comportamento quadratico. (Un ordinamento stabile preserva l'ordine degli elementi in input che risultano uguali. Benché il tempo d'esecuzione di quicksort sia O(NlogN) in media su tutti gli array di lunghezza N, il tempo può essere O(N**2), ovvero comportarsi quadraticamente, per alcuni input). Nella versione 5.7, l'implementazione di quicksort è stata rimpiazzata da un algoritmo mergesort stabile il cui comportamento nel caso pessimo è O(NlogN). Ma i benchmark indicavano che per alcuni input, su alcune piattaforme, il quicksort originale andava più veloce. La versione 5.8 ha una direttiva sort che consente un limitato controllo su sort. Il suo blando controllo dell'algoritmo sottostante potrebbe scomparire nelle prossime versioni di Perl, ma l'abilità di caratterizzare l'input e l'output in modi indipendenti dall'implementazione probabilmente non lo farà. Consultate sort.
Esempi:
# ordinamento lessicale
@articoli = sort @file;
# stessa cosa, ma con una routine esplicita di ordinamento
@articoli = sort {$a cmp $b} @file;
# ora senza tener conto di maiuscole e minuscole
@articoli = sort {uc($a) cmp uc($b)} @file;
# stessa cosa in ordine inverso
@articoli = sort {$b cmp $a} @file;
# ordinamento numerico ascendente
@articoli = sort {$a <=> $b} @file;
# ordinamento numerico discendente
@articoli = sort {$b <=> $a} @file;
# ordina l'hash %eta per valore anziche' per chiave
# usando una funzione interna
@prima_gli_anziani = sort { $eta{$b} <=> $eta{$a} } keys %eta;
# ordina usando il nome della subroutine esplicito
sub pereta {
$eta{$a} <=> $eta{$b}; # si assume siano chiavi numeriche
}
@classe_ordinata = sort pereta @classe;
sub alcontrario { $b cmp $a }
@harry = qw(cane gatto x Caino Abele);
@george = qw(andato inseguito yz Punito Accettato);
print sort @harry;
# stampa AbelCaincatdogx AbeleCainocanegattox
print sort alcontrario @harry;
# stampa xdogcatCainAbel xgattocaneCainoAbele
print sort @george, 'to', @harry;
# stampa AbeleAccettatoCainoPunitoandatocanegattoinseguitotoxyz
# ordinamento inefficiente ottenuto per confronto
# numerico discendente del primo numero dopo
# il primo segno =, o altrimenti per confronto
# di tutto il record, senza tener conto di
# maiuscole e minuscole
@nuovo = sort {
($b =~ /=(\d+)/)[0] <=> ($a =~ /=(\d+)/)[0]
||
uc($a) cmp uc($b)
} @vecchio;
# stessa cosa, ma in maniera molto piu` efficiente;
# costruiamo indici ausiliari, per aumentare la
# velocita`
@numeri = @inmaiuscolo = ();
for (@vecchio) {
push @numeri, /=(\d+)/;
push @inmaiuscolo, uc($_);
}
@nuovo = @vecchio[ sort {
$numeri[$b] <=> $numeri[$a]
||
$caps[$a] cmp $caps[$b]
} 0..$vecchio
];
# stessa cosa, ma senza variabili temporanee
@nuovo = map { $_->[0] }
sort { $b->[1] <=> $a->[1]
||
$a->[2] cmp $b->[2]
} map { [$_, /=(\d+)/, uc($_)] } @vecchio;
# l'uso di un prototipo consente di usare, con sort,
# qualunque subroutine di confronto (comprese le
# subroutine definite in altri package)
package altro;
sub alcontrario ($$) { $_[1] cmp $_[0]; } # $a e $b, qui, non sono impostate
package main;
@nuovo = sort altro::alcontrario @vecchio;
# stabilita` garantita, qualunque sia l'algoritmo
use sort 'stable';
@nuovo = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @vecchio;
# forza l'uso di mergesort (non portabile al di
# fuori della versione 5.8 di Perl)
use sort '_mergesort'; # notate il _ che ne
# scoraggia l'uso
@nuovo = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @vecchio;
Se state usando strict, non dovete dichiarare $a e
$b come lessicali. Sono variabili globali del package.
Questo significa che se siete nel package main e
scrivete
@articoli = sort { $b <=> $a } @file;
allora $a e $b sono $main::a e $main::b
(o $::a e $::b), ma se siete nel package
PackagePippo è lo stesso che scrivere
@articoli = sort { $PackagePippo::b <=> $PackagePippo::a } @file;
Si richiede che la funzione di confronto si comporti
in modo consistente. Se restituisce risultati
inconsistenti (dicendo a volte che $x[1] è
più piccolo di $x[2] e a volte il contrario,
per esempio) i risultati non sono ben definiti.
Poiché <=> restituisce undef quando uno degli operandi è
NaN (not-a-number) [non-un-numero, NdT], e poiché sort genererà
un errore bloccante a meno che il risultato del confronto sia definito, quando
effettuate un ordinamento con una funzione di confronto come $a <= $b>,
state attenti alle liste che potrebbero contenere NaN. Il seguente esempio sfrutta
il fatto che NaN != NaN, per eliminare ogni NaN dall'input.
@risultati = sort { $a <=> $b } grep { $_ == $_ } @input;