Precedente: , Su: Ordinamento di vettori   [Contenuti][Indice]


12.2.2 Ordinare valori e indici di un vettore con 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 che asort() 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

Note a piè di pagina

(90)

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: , Su: Ordinamento di vettori   [Contenuti][Indice]