swift

Map è un metodo del tipo array, ovvero una delle tante funzioni che la struttura array mette a disposizione per manipolare i propri elementi. Trovo che sia una funzione molto utile che in alcuni casi semplifica veramente il lavoro. Partiamo dal caso tipico di un array di numeri sui quali reiteriamo per effettuare un'operazione ad esempio di elevamento a potenza.

var numeri = [1, 23, 14, 76, 234]

var nuovo = [Int]()

for i in numeri {

    let tmp = i * i

    nuovo.append(tmp)

}

 

Inizializziamo l'array numeri con valori a caso e inizializziamo l'array di destinazione in cui riporre i valori dopo il calcolo. Eseguiamo il ciclo for e mettiamo in append nel nuovo array i valori calcolati. Tutto questo è molto semplice, incredibilmente lo può essere di più.

Introduciamo l'uso del metodo map facendoci aiutare da Xcode, digitiamo il nome dell'array (numeri) premiamo il punto e selezioniamo il metodo map, poi premiamo invio due volte, questo è quello che compare.

numeri.map { (<#Int#>) -> T in

    <#code#>

}  

 

Xcode propone di inserire una closure come parametro del metodo map (ovvero una funzione descritta in modo sintetico dalla closure). Ricordando quanto esposto nel paragrafo closures completiamo il codice come di seguito. Il primo segnaposto da sostituire riguarda il nome e il tipo di variabile passata alla funzione map. Con la lettera 'T' il compilatore indica un contenitore generico, in quanto l'operazione che effettuiamo su ogni elemento dell'array potrebbe restituire qualsiasi tipo (es. prendo Int e restituisco String); la nostra procedura restituisce un intero ed è quello che viene scritto al posto di 'T'. Infine il codice da applicare ad ogni elemento, nel nostro caso l'elevamento a potenza.

let nuovoArray = numeri.map { (i: Int) -> Int in

    return i * i

}  

 

Map reitera su tutti gli elementi dell'array prendendo il loro valore intero, effettuando l'operazione indicata e ritornando un'altro valore intero che viene riposto in nuovoArray. Facendo sempre riferimento al paragrafo closure l'espressione sopra esposta può essere ulteriormente semplificata raggiungendo la sua forma minimale.

let ancoraNuovoArray = numeri.map { $0 * $0 }

Reduce è una proprietà del tipo array come map. Condivide con map il fatto che il compilatore dietro le quinte reitera su tutti gli elementi dell'array per effettuare su ogniuno di essi un'operazione. Lo scopo di reduce è quello di ridurre gli elementi dell'array ad un singolo elemento; l'utilizzo tipico è quello di ottenere la somma o il prodotto di tutti i valori di un array.

let totale = numeri.reduce(0, { parziale, successivo in

    return parziale + successivo

}) 

 

In questo esempio si fa la somma di tutti i valori dell'array numeri definito in precedenza. Il primo valore '0' specificato in reduce è da considerarsi una sorta di offset, un valore che viene sommato al risultato finale, oppure un valore di partenza a cui vengono sommati tutti i successivi. Parziale indica il risultato parziale man mano che la procedura reitera sugli elementi dell'array effettuando l'operazione indicata nel corpo della funzione. Nell'esempio ad ogni ciclo parziale viene aggiornato con il valore corrente cioè la somma parziale. Successivo è il valore in successione dell'array. La procedura sopra esposta per ogni elemento dell'array effettua la somma tra il valore parziale e il successivo e lo ripone in parziale.

Sfruttando quanto imparato con le closures si può semplificare il codice sopra esposto scrivendo:

let totale2 = numeri.reduce(0, { $0 + $1 })

 

Filter è un'altra proprietà degli array che reiterando su tutti gli elementi fornisce un valore vero o falso sulla base di un filtro specificato. Anche filter fa uso delle closures.

let numeriPari = numeri.filter { (valore: Int) -> Bool in

    return valore % 2 == 0
}

Valore è l'elemento dell'array su cui reitera la funzione e viene utilizzato per capire ad ogni ciclo se è pari oppure no. Il codice esposto restituisce i soli valori pari dell'array numeri. Ricordando la capacità di sintesi delle closures l'espressione sopra esposta può essere così rappresentata:

let numeriPari2 = numeri.filter { $0 % 2 == 0 }