Successivo: , Precedente: , Su: Vettori   [Contenuti][Indice]


8.6 Vettori di vettori

gawk migliora l’accesso ai vettori multidimensionali di awk standard e mette a disposizione dei veri vettori di vettori. Agli elementi di un sottovettore si fa riferimento tramite il loro indice racchiuso tra parentesi quadre, proprio come gli elementi del vettore principale. Per esempio, quel che segue crea un sottovettore con due elementi all’indice 1 del vettore principale a:

a[1][1] = 1
a[1][2] = 2

Questo simula un vero vettore bidimensionale. Ogni elemento di un sottovettore può contenere un altro sottovettore come valore, che a sua volta può contenere anche ulteriori vettori. In questo modo, si possono creare vettori di tre o più dimensioni. Gli indici possono essere costituiti da qualunque espressione di awk, compresi dei valori scalari separati da virgole (cioè, un indice multidimensionale simulato di awk). Quindi, la seguente espressione è valida in gawk:

a[1][3][1, "nome"] = "barney"

Ogni sottovettore e il vettore principale possono essere di diversa lunghezza. Di fatto, gli elementi di un vettore o un suo sottovettore non devono essere necessariamente tutti dello stesso tipo. Ciò significa che il vettore principale come anche uno qualsiasi dei suoi sottovettori può essere non rettangolare, o avere una struttura frastagliata. Si può assegnare un valore scalare all’indice 4 del vettore principale a, anche se a[1] è esso stesso un vettore e non uno scalare:

a[4] = "Un elemento in un vettore frastagliato"

I termini dimensione, riga e colonna sono privi di significato quando sono applicati a questo tipo di vettore, ma d’ora in poi useremo “dimensione” per indicare il numero massimo di indici necessario per far riferimento a un elemento esistente. Il tipo di ogni elemento che è già stato assegnato non può essere cambiato assegnando un valore di tipo diverso. Prima si deve eliminare l’elemento corrente, per togliere completamente dalla memoria di gawk ogni riferimento a quell’indice:

delete a[4]
a[4][5][6][7] = "Un elemento in un vettore quadridimensionale"

Le due istruzioni rimuovono il valore scalare dall’indice 4 e inseriscono poi un sottovettore interno a tre indici contenente uno scalare. Si può anche eliminare un intero sottovettore o un sottovettore di sottovettori:

delete a[4][5]
a[4][5] = "Un elemento nel sottovettore a[4]"

Si deve però ricordare che non è consentito eliminare il vettore principale a e poi usarlo come scalare.

Le funzioni predefinite che accettano come argomenti dei vettori possono essere usate anche con i sottovettori. Per esempio, il seguente frammento di codice usa length() (vedi la sezione Funzioni di manipolazione di stringhe) per determinare il numero di elementi nel vettore principale a e nei suoi sottovettori:

print length(a), length(a[1]), length(a[1][3])

Il risultato per il nostro vettore principale a è il seguente:

2, 3, 1

L’espressione ‘indice in vettore’ (vedi la sezione Come esaminare un elemento di un vettore) funziona allo stesso modo sia per i vettori regolari in stile awk che per i vettori di vettori. Per esempio, le espressioni ‘1 in a’, ‘3 in a[1]’ e ‘(1, "nome") in a[1][3]’ risultano tutte di valore uno (vero) per il nostro vettore a.

L’istruzione ‘for (elemento in vettore)’ (vedi la sezione Visitare tutti gli elementi di un vettore) può essere nidificata per visitare tutti gli elementi di un vettore di vettori che abbia una struttura rettangolare. Per stampare il contenuto (valori scalari) di un vettore di vettori bidimensionale (cioè nel quale ogni elemento di primo livello è esso stesso un vettore, non necessariamente di lunghezza uguale agli altri) si può usare il seguente codice:

for (i in vettore)
    for (j in vettore[i])
        print vettore[i][j]

La funzione isarray() (vedi la sezione Funzioni per conoscere il tipo di una variabile) permette di verificare se un elemento di un vettore è esso stesso un vettore:

for (i in vettore) {
    if (isarray(vettore[i])) {
        for (j in vettore[i]) {
            print vettore[i][j]
        }
    }
    else
        print vettore[i]
}

Se la struttura di un vettore di vettori frastagliato è nota in anticipo, si può spesso trovare il modo per visitarlo usando istruzioni di controllo. Per esempio, il seguente codice stampa gli elementi del nostro vettore principale a:

for (i in a) {
    for (j in a[i]) {
        if (j == 3) {
            for (k in a[i][j])
                print a[i][j][k]
        } else
            print a[i][j]
    }
}

Vedi la sezione Attraversare vettori di vettori per una funzione definita dall’utente che “visita” un vettore di vettori di dimensioni arbitrarie.

Si ricordi che un riferimento a un elemento di un vettore non inizializzato genera un elemento con valore uguale a "", la stringa nulla. Questo ha un’importante implicazione quando s’intende usare un sottovettore come argomento di una funzione, come illustrato nel seguente esempio:

$ gawk 'BEGIN { split("a b c d", b[1]); print b[1][1] }'
error→ gawk: riga com.:1: fatale: split: secondo argomento
error→                                      non-vettoriale

Il modo per aggirare quest’ostacolo è quello di definire prima b[1] come vettore creando un indice arbitrario:

$ gawk 'BEGIN { b[1][1] = ""; split("a b c d", b[1]); print b[1][1] }'
-| a

Successivo: , Precedente: , Su: Vettori   [Contenuti][Indice]