Sotto-Array in JavaScript

Concetti Chiave
  • In JavaScript, possiamo lavorare con i sotto-array utilizzando i metodi slice, splice, fill e copyWithin.
  • Il metodo slice restituisce una porzione di un array, specificando l'indice di inizio e di fine, senza modificare l'array originale.
  • Il metodo splice consente di rimuovere o inserire elementi in un array, modificando l'array originale, e restituisce gli elementi rimossi.
  • Il metodo fill imposta gli elementi di un array a un valore specificato, modificando l'array originale, e può essere utilizzato per riempire una sezione dell'array.
  • Il metodo copyWithin copia una porzione di un array in una nuova posizione all'interno dello stesso array, senza modificare la lunghezza dell'array, e restituisce l'array modificato.

Sotto-array

Gli array definiscono una serie di metodi che funzionano su regioni contigue, o sotto-vettori o "fette" di un array (in inglese slice).

Vediamo alcuni di questi metodi.

slice

Il metodo slice() restituisce una fetta, o sotto-array, dell'array specificato. I suoi due argomenti specificano l'inizio e la fine della fetta da restituire. L'array restituito contiene l'elemento specificato dal primo argomento e tutti gli elementi successivi fino a, ma non incluso, l'elemento specificato dal secondo argomento.

Se viene specificato solo un argomento, l'array restituito contiene tutti gli elementi dalla posizione di inizio alla fine dell'array. Se uno dei due argomenti è negativo, esso specifica un elemento dell'array relativo alla lunghezza dell'array. Un argomento di -1, per esempio, specifica l'ultimo elemento nell'array, e un argomento di -2 specifica il penultimo.

Si noti che slice() non modifica l'array su cui viene invocato.

Vediamo qualche esempio:

// Array di partenza
let a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Restituisce gli elementi partendo
// dall'indice 0 fino all'indice 3 escluso
a.slice(0, 3);    // Restituisce [1, 2, 3]

// Restituisce gli elementi partendo
// dall'indice 3 fino alla fine dell'array
a.slice(3);       // Restituisce [4, 5, 6, 7, 8, 9, 10]

// Restituisce gli elementi partendo
// dall'indice 1, fino all'ultimo elemento escluso
a.slice(1, -1);   // Restituisce [2, 3, 4, 5, 6, 7, 8, 9]

// Restituisce gli ultimi 3 elementi dell'array
a.slice(-3); // Restituisce [8, 9, 10]

// Restituisce gli elementi dal terzultimo fino
// all'ultimo escluso
a.slice(-3, -1); // Restituisce [8, 9]

splice

splice() è un metodo generico per inserire o rimuovere elementi da un array.

A differenza di slice() e concat(), splice() modifica l'array su cui viene invocato.

Si noti che splice() e slice() hanno nomi molto simili ma eseguono operazioni sostanzialmente diverse.

splice() può eliminare elementi da un array, inserire nuovi elementi in un array, o eseguire entrambe le operazioni contemporaneamente. Gli elementi dell'array che vengono dopo il punto di inserimento o eliminazione hanno i loro indici aumentati o diminuiti se necessario in modo che rimangano contigui con il resto dell'array.

Il primo argomento di splice() specifica la posizione dell'array alla quale l'inserimento e/o l'eliminazione deve iniziare. Il secondo argomento specifica il numero di elementi che dovrebbero essere eliminati dall'array. Notiamo che questa è un'altra differenza tra questi due metodi, infatti il secondo argomento di slice() è una posizione finale. Il secondo argomento di splice() è una lunghezza. Se questo secondo argomento viene omesso, tutti gli elementi dell'array dall'elemento iniziale alla fine dell'array vengono rimossi. splice() restituisce un array degli elementi eliminati, o un array vuoto se nessun elemento è stato eliminato.

Per esempio:

// Array di partenza
let a = [1, 2, 3, 4, 5, 6, 7, 8];

// Rimuove tutti gli elementi a partire dall'indice 4
// Restituisce [5, 6, 7, 8]
// a è ora [1, 2, 3, 4]
a.splice(4);

// Rimuove 2 elementi a partire dall'indice 1
// Restituisce [2, 3]
// a è ora [1, 4]
a.splice(1,2);

// Rimuove 1 elemento a partire dall'indice 1
// Restituisce [4]
// a è ora [1]
a.splice(1,1);

I primi due argomenti di splice() specificano quali elementi dell'array devono essere eliminati. Questi argomenti possono essere seguiti da qualsiasi numero di argomenti aggiuntivi che specificano elementi da inserire nell'array, iniziando dalla posizione specificata dal primo argomento.

Per esempio:

// Array di partenza
let a = [1, 2, 3, 4, 5];

// Rimuove gli ultimi due elementi
// ed aggiunge gli elementi 6 e 7
a.splice(3, 2, 6, 7); // Restituisce [4, 5]; a è ora [1, 2, 3, 6, 7]

// Rimuove 2 elementi a partire dall'indice 2
// ed aggiunge due elementi:
// - un array
// - la stringa "ciao"
a.splice(2, 2, [1, 2], "ciao"); // Restituisce [3, 6]; a è ora [1, 2, [1, 2], "ciao", 7]

Si noti che, a differenza di concat(), splice() inserisce gli array stessi, non gli elementi di quegli array. Quindi non effettua nessun appiattimento.

fill

Il metodo fill() imposta gli elementi di un array, o una sezione di un array, a un valore specificato. Modifica l'array su cui è chiamato, e restituisce anche l'array modificato:

let a = new Array(5);   // Inizia senza elementi e lunghezza 5
a.fill(0)               // => [0,0,0,0,0]; riempie l'array con zeri
a.fill(9, 1)            // => [0,9,9,9,9]; riempie con 9 partendo dall'indice 1
a.fill(8, 2, -1)        // => [0,9,8,8,9]; riempie con 8 agli indici 2, 3

Il primo argomento di fill() è il valore con cui impostare gli elementi dell'array. Il secondo argomento opzionale specifica l'indice di partenza. Se omesso, il riempimento inizia dall'indice 0. Il terzo argomento opzionale specifica l'indice di fine: gli elementi dell'array fino a, ma non incluso, questo indice saranno riempiti. Se questo argomento è omesso, allora l'array viene riempito dall'indice di partenza fino alla fine. Possiamo specificare indici relativi alla fine dell'array passando numeri negativi, proprio come possiamo fare per slice().

copyWithin

copyWithin() copia una porzione di un array in una nuova posizione all'interno dello stesso array. Modifica l'array in place e restituisce l'array modificato, ma non cambierà la lunghezza dell'array.

Il primo argomento specifica l'indice di destinazione a cui il primo elemento sarà copiato. Il secondo argomento specifica l'indice del primo elemento da copiare. Se questo secondo argomento viene omesso, viene utilizzato 0. Il terzo argomento specifica la fine della porzione di elementi da copiare. Se omesso, viene utilizzata la lunghezza dell'array. Gli elementi dall'indice di inizio fino a, ma non incluso, l'indice di fine saranno copiati. È possibile specificare indici relativi alla fine dell'array passando numeri negativi, proprio come si può fare per slice():

let a = [1,2,3,4,5];
a.copyWithin(1)       // => [1,1,2,3,4]:
                      //    copia gli elementi dell'array di una posizione in su
a.copyWithin(2, 3, 5) // => [1,1,3,4,4]: copia gli ultimi 2 elementi all'indice 2
a.copyWithin(0, -2)   // => [4,4,3,4,4]: anche gli offset negativi funzionano

copyWithin() è concepito come un metodo ad alte prestazioni che è particolarmente utile con gli array tipizzati (che vedremo nelle prossime lezioni).

È modellato sulla funzione memmove() della libreria standard C. Si noti che la copia funzionerà correttamente anche se c'è sovrapposizione tra le regioni sorgente e destinazione.