Precedente: Controllare visita vettori, Su: Ordinamento di vettori [Contenuti][Indice]
gawk
Nella maggior parte delle implementazioni di awk
, ordinare un vettore
richiede una funzione sort()
. Questo può essere istruttivo per provare
diversi algoritmi di ordinamento, ma normalmente non è questo lo scopo del
programma. In gawk
ci sono le funzioni predefinite asort()
e
asorti()
(vedi la sezione Funzioni di manipolazione di stringhe) per i vettori ordinati.
Per esempio:
riempire il vettore dati n = asort(dati) for (i = 1; i <= n; i++) fare qualcosa con dati[i]
Dopo la chiamata ad asort()
, il vettore dati
è indicizzato da 1
a n, il numero totale di elementi in dati
.
(Questo conteggio è il codice di ritorno di asort()
).
dati[1]
<= dati[2]
<= dati[3]
, e così
via. Il confronto di default è basato sul tipo di elementi
(vedi la sezione Tipi di variabile ed espressioni di confronto).
Tutti i valori numerici vengono prima dei valori di stringa,
che a loro volta vengono prima di tutti i sottovettori.
Un effetto collaterale rilevante nel chiamare asort()
è che
gli indici originali del vettore vengono persi irreparabilmente.
Poiché questo non sempre è opportuno, asort()
accetta un
secondo argomento:
populate the array orig n = asort(orig, dest) for (i = 1; i <= n; i++) fai qualcosaa con dest[i]
In questo caso, gawk
copia il vettore orig
nel vettore
dest
e ordina dest
, distruggendo i suoi indici.
Tuttavia il vettore orig
non viene modificato.
Spesso, ciò di cui si ha bisogno è di ordinare per i valori degli
indici invece che per i valori degli elementi. Per far questo si usa la
funzione asorti()
. L’interfaccia e il comportamento sono identici a
quelli di asort()
, solo che per l’ordinamento vengono usati i valori
degli indici, che diventano i valori del vettore risultato:
{ orig[$0] = una_funz($0) } END { n = asorti(orig, dest) for (i = 1; i <= n; i++) { Lavora direttamente con gli indici ordinati: fa qualcosa con dest[i] … Accede al vettore originale attraverso gli indici ordinati: fa qualcosa con orig[dest[i]] } }
Fin qui, tutto bene. Ora inizia la parte interessante. Sia asort()
che asorti()
accettano un terzo argomento di stringa per controllare il
confronto di elementi del vettore. Quando abbiamo introdotto asort()
e
asorti()
nella Funzioni di manipolazione di stringhe, abbiamo ignorato questo terzo
argomento; comunque, è giunto il momento di descrivere come questo argomento
influenza queste due funzioni.
Fondamentalmente, il terzo argomento specifica come dev’essere ordinato il
vettore. Ci sono due possibilità. Come per PROCINFO["sorted_in"]
,
quest’argomento può essere uno degli argomenti predefiniti che gawk
fornisce (vedi la sezione Visita di vettori in ordine predefinito con gawk
), o può essere il nome di una funzione
definita dall’utente (vedi la sezione Controllare visita vettori).
Nell’ultimo caso, la funzione può confrontare gli elementi in qualunque modo si voglia, prendendo in considerazione solo gli indici, solo i valori, o entrambi. Questo è estremamente potente.
Una volta che il vettore è ordinato, asort()
prende i valori nel
loro ordine finale e li usa per riempire il vettore risultato, mentre
asorti()
prende gli indici nel loro ordine finale e li usa per
riempire il vettore risultato.
NOTA: Copiare indici ed elementi non è dispendioso in termini di memoria. Internamente,
gawk
mantiene un conteggio dei riferimenti ai dati. Per esempio, dopo cheasort()
copia il primo vettore nel secondo, in memoria c’è ancora una sola copia dei dati degli elementi del vettore originale, ed entrambi i vettori accedono all’unica copia di valori che esiste in memoria.
Poiché IGNORECASE
influenza i confronti tra stringhe, il valore di
IGNORECASE
influisce anche sull’ordinamento sia con asort()
che
con asorti()
.
Si noti inoltre che l’ordinamento della localizzazione non entra in
gioco; i confronti sono basati solamente sul valore dei
caratteri.90
L’esempio seguente mostra l’uso di una funzione di confronto usata con
asort()
. La funzione di confronto, confronta_in_minuscolo()
,
trasforma gli elementi da confrontare in lettere minuscole, in modo da avere
confronti che non dipendono da maiuscolo/minuscolo.
# confronta_in_minuscolo --- confronta stringhe ignorando maiuscolo/minuscolo function confronta_in_minuscolo(i1, v1, i2, v2, l, r) { l = tolower(v1)
r = tolower(v2) if (l < r) return -1 else if (l == r) return 0 else return 1 }
E questo programma può essere usato per provarla:
# programma di test BEGIN { Letters = "abcdefghijklmnopqrstuvwxyz" \ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" split(Letters, data, "") asort(data, risultato, "confronta_in_minuscolo") j = length(risultato) # numero elementi del vettore "risultato" for (i = 1; i <= j; i++) { printf("%s", risultato[i]) if (i % (j/2) == 0) # a metà, la stampa del vettore va a capo printf("\n") else printf(" ") } }
Se si esegue il programma, si ottiene:
$ gawk -f confronta_in_minuscolo.awk -| A a B b c C D d e E F f g G H h i I J j k K l L M m -| n N O o p P Q q r R S s t T u U V v w W X x y Y z Z
Ciò è vero perché il confronto basato sulla localizzazione
avviene solo quando si è in modalità POSIX-compatibile, e poiché asort()
e asorti()
sono estensioni di gawk
, esse non sono disponibili
in quel caso.
Precedente: Controllare visita vettori, Su: Ordinamento di vettori [Contenuti][Indice]