Accedi come Scuola



Array e Iteratori

Scriviamo un programma che ci chieda d'inserire tante parole quante ne vogliamo (una parola per linea, continuando finché non premiamo Invio su una linea vuota), e che quindi ci ripeta le stesse parole in ordine alfabetico. Ok?

Quindi... per prima cosa scriveremo... uh... uhm... mmmh... Beh, potremmo... ehm... uhm...

Sai che ti dico? Non credo che lo possiamo fare. Ci servirebbe un qualcosa per immagazzinare un numero sconosciuto di parole, tenendo traccia di ciascuna di esse, così che non si mischino con altre variabili. Dovremmo poter mettere queste parole in una specie di lista. In altre parole, ci servono gli array.
(NdC: "array" è un termine informatico che generalmente non si traduce, in italiano ha diversi significati).

Un array è semplicemente una lista nel tuo computer. Ogni posizione nella lista si comporta esattamente come una variabile: puoi vedere a quale oggetto punta ciascuna posizione e puoi farla puntare a un altro oggetto. Diamo un'occhiata a un po' di array:

# encoding: utf-8
[]
[5]
['Ciao', 'Arrivederci']

gusto = 'vaniglia'            #  Questo non è un array, ovviamente...
[89.9, gusto, [true, false]]  #  ...mentre questo lo è.

Il primo è un array vuoto, il secondo un array che contiene un solo numero (un intero), quindi un array che contiene due stringhe. Poi abbiamo un semplice assegnamento; e infine un array che contiene tre oggetti, l'ultimo dei quali è l'array [truefalse]. Ricorda: le variabili non sono oggetti, quindi il nostro ultimo array in realtà sta puntando a un float, a una stringa e a un array. Anche se successivamente dovessimo far puntare gusto a qualcos'altro, l'array non cambierebbe.

Per aiutarci a trovare un particolare oggetto in un array, a ciascuna posizione è assegnato un indice numerico. I programmatori (e, per inciso, la maggior parte dei matematici) contano partendo dallo zero, quindi la prima posizione nell'array è la posizione zero. Ecco come ci riferiremo ai singoli oggetti nell'array:

# encoding: utf-8
nomi = ['Ada', 'Bella', 'Chris']

puts nomi
puts nomi[0]
puts nomi[1]
puts nomi[2]
puts nomi[3]  #  Questo è fuori portata (out of range).
Ada
Bella
Chris
Ada
Bella
Chris
nil

Allora, notiamo come puts nomi stampa ciascun nome contenuto nell'array nomi. Quindi usiamo puts nomi[0] per stampare il "primo" nome nell'array, e puts nomi[1] per stampare il "secondo"... Sono sicuro che sembra incasinato, ma ci farai l'abitudine. Devi solo cominciare a pensare che il conteggio comincia dallo zero, e smetterla di usare parole come "primo" e "secondo". Se sei invitato a un pranzo di cinque portate, la prima portata non chiamarla "primo"; chiamala portata zero (e nella tua testa immaginatela come portate[0]). Hai cinque dita della mano destra, e i loro numeri sono 0, 1, 2, 3 e 4. Mia moglie ed io siamo giocolieri. Quando facciamo roteare 6 palline contemporaneamente, stiamo facendo roteare le palline 0-5. Speriamo nei prossimi mesi di imparare a far roteare anche la pallina 6 (di conseguenza riusciremo a farne roteare 7). Saprai di aver afferrato il concetto quando comincerai a usare la parola "zeresimo". :-) Sì, è una parola che esiste davvero; chiedi a qualsiasi programmatore o matematico.

Infine, abbiamo provato il comando puts nomi[3], solo per vedere cosa sarebbe accaduto. Ti aspettavi un errore? A volte quando fai una domanda, la tua domanda non ha senso (almeno secondo il tuo computer); e questo è quando ottieni un errore. Altre volte, invece, puoi la risposta alla tua domande è niente. Cosa c'è nella posizione tre? Niente. Cos'è nomi[3]? nil: E' così che Ruby ti risponde "niente". nil è un oggetto speciale che sostanzialmente significa "nessun altro oggetto" o "niente, letteralmente".

Se questo buffo modo di numerare le posizioni negli array ti lascia perplesso, non aver paura! Spesso possiamo evitarlo completamente usando diversi metodi, come questo:

Il metodo each

each (che vuol dire "ciascuno") ci permette di fare qualcosa (qualsiasi cosa essa sia) a ciascun oggetto cui punta l'array. Quindi, se volessimo dire qualcosa di carino a proposito di ciascun linguaggio nell'array qui sotto, faremmo in questo modo:

# encoding: utf-8
linguaggi = ['Italiano', 'Inglese', 'Ruby']

linguaggi.each do |ling|
  puts 'Amo scrivere in ' + ling + '!'
  puts 'E tu?'
end

puts 'E che mi dici del C++?'
puts '...'
Amo scrivere in Italiano!
E tu?
Amo scrivere in Inglese!
E tu?
Amo scrivere in Ruby!
E tu?
E che mi dici del C++?
...

Allora, cos'è successo? Beh, siamo stati in grado di passare per ogni oggetto nell'array senza usare nessun numero, il che è sicuramente piacevole. Tradotto in Italiano, il programma di sopra si leggerebbe più o meno così: Per each (ciascun) oggetto in linguaggi, punta la variabile ling all'oggetto e quindi do (fai) tutto quello che ti dico, finché non arrivi a end (fine). (Giusto perché tu lo sappia, C++ è un altro linguaggio di programmazione. E' molto più difficile da imparare rispetto a Ruby; di solito un programma scritto in C++ è molte volte più lungo di un programma scritto in Ruby che fa la stessa cosa).

Potresti star pensando tra te e te, "Questo assomiglia molto ai loop visti prima." Già, è simile. Una importante differenza consiste nel fatto che il metodo each è giusto quello che è: un metodo. Mentre while e end (esattamente come do, if, else, e tutte le altre parole blu) non sono metodi. Sono parti fondamentali del linguaggio Ruby, proprio come = e le parentesi; un po' come la punteggiatura in Italiano.

Ma non each; each è solo un altro metodo degli array. Metodi come each che si "comportano come" dei loop, sono spesso chiamati iteratori.

Una cosa da notare sugli iteratori è che sono sempre seguiti da do...end. while e if non hanno mai un do vicino; do lo usiamo solo con gli iteratori.

Ed ecco un altro piccolo iteratorino, ma non è un metodo degli array... è un metodo dei numeri interi!

# encoding: utf-8
3.times do
  puts 'Hip-Hip-Urrà!'
end
Hip-Hip-Urrà!
Hip-Hip-Urrà!
Hip-Hip-Urrà!

[NdC: "times" in inglese vuol dire "volte", quindi "3.times do" diventa "3.volte fai", visto com'è facile Ruby se si conosce anche solo un minimo d'inglese?]

Altri Metodi degli Array

Abbiamo imparato each, ma gli Array hanno tanti altri metodi... ne hanno quasi tanti quanto ne hanno le stringhe! Infatti, alcuni di loro (come length (lunghezza), reverse (inverti), +, e *) funzionano esattamente come per le stringhe, con l'eccezione che operano sulle posizioni dell'array invece che sulle lettere della stringa. Altri, come last (ultimo) e join (collega), sono invece specifici degli array. Altri ancora, come push (premi) e pop (stappa), modificano effettivamente l'array. Ma, proprio come per i metodi delle stringhe, non sei tenuto a ricordarteli tutti, finché ti ricordi dove poterli trovare (per esempio, proprio qui).

Innanzitutto, vediamo to_s e join. join funziona in modo simile a to_s, con l'eccezione che aggiunge una stringa fra gli oggetti dell'array. Vediamo un po':

# encoding: utf-8
cibi = ['carciofo', 'brioche', 'caramello']

puts cibi
puts
puts cibi.to_s
puts
puts cibi.join(', ')
puts
puts cibi.join('  :)  ') + '  8)'

200.times do
  puts []
end
carciofo
brioche
caramello

carciofobriochecaramello

carciofo, brioche, caramello

carciofo  :)  brioche  :)  caramello  8)

Come puoi vedere, puts tratta gli array in modo diverso rispetto agli altri oggetti: semplicemente chiama puts su ciascuno degli oggetti nell'array. Ed è per questo che "putsare" un array vuoto 200 volte non fa nulla; l'array non punta a nulla, quindi non c'è nulla per puts. (Far niente per 200 volte è sempre far niente.) Prova a "putsare" un array che contiene altri array; ha fatto quello che ti aspettavi?

Inoltre, hai notato che ho chiamato puts su niente per lasciare una riga vuota? E' per lo stesso principio.

Ora, diamo un'occhiata a push, pop, e last. I metodi push e pop sono complementari, un po' come + e -. push aggiunge un oggetto alla fine dell'array, mentre pop rimuove l'ultimo oggetto dall'array (e ti dice qual era). last è simile a pop, ti dice cosa c'è alla fine dell'array, però non lo modifica ( non rimuove l'ultimo oggetto). Ancora, push e pop modificano effettivamente l'array:

# encoding: utf-8
favorite = []
favorite.push 'rugiada sulle rose'
favorfavoriteites.push 'whiskey sui gattini'

puts favorite[0]
puts favorite.last
puts favorite.length

puts favorite.pop
puts favorite
puts favorite.length
rugiada sulle rose
whiskey sui gattini
2
whiskey sui gattini
whiskey sui gattini
1

Un Po' di Cose da Provare

  • Scrivi il programma di cui abbiamo parlato proprio all'inizio di questo capitolo.
    Suggerimento: C'è un adorabile metodo degli array che restituisce una versione ordinata dello stesso array: sort (ordina). Usalo!
  • Riscrivi il nostro programma Indice. Comincia il programma con un array che contiene tutte le informazioni per l'Indice (nomi dei capitoli, numeri delle pagine etc.) Quindi stampa le informazioni dell'array in un Indice meravigliosamente formattato.

Le soluzioni sono disponibili nel Manuale delle Soluzioni :)

Finora abbiamo imparato un bel numero di metodi differenti. Direi che è arrivato il momento d'imparare come creare i nostri.

Che ne dici?

Scritto da

Duccio Armenise

Founder Corsidia & co-Founder WorldBridge

Aiuto solo i migliori Maestri a trovare i loro prossimi Studenti. Come? Così! :)

Per

Corsidia

I tuoi prossimi Studenti ti stanno già cercando, tu ci sei?