Uno degli obiettivi principali di Julia è poter eseguire calcoli su dati numerici in modo rapido ed efficiente. Molti dati numerici.
Di solito i dati vengono memorizzati in array (o in qualche tipo correlato), quindi si può ben dire che gli array sono al cuore del linguaggio Julia.
Gli array possono avere dimensioni arbitrarie (limitate solo dalla memoria disponibile nell'hardware) e possono avere un numero arbitrario di dimensioni.
Questo concetto introduttivo si concentra sulle basi degli array monodimensionali, che vengono chiamati Vector.
In Julia, un Vector è una sequenza ordinata di valori a cui si può accedere tramite un indice numerico.
Il modo più semplice per creare un Vector è elencare i valori tra parentesi quadre:
julia> num_vec = [1, 4, 9]
3-element Vector{Int64}:
1
4
9
julia> str_vec = ["arrays", "are", "important"]
3-element Vector{String}:
"arrays"
"are"
"important"
Il tipo di un Vector coincide con il tipo dei suoi elementi.
Quindi i Vector devono essere omogenei (tutti gli elementi dello stesso tipo)?
A un certo livello, sì, ed è consigliabile puntarci se vuoi ottenere le prestazioni migliori.
Tuttavia, Julia può aggirare questo limite (quando necessario) usando il tipo Any:
julia> mixed_vector = [1, "str", 'c']
3-element Vector{Any}:
1
"str"
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
Quando si crea un Vector vuoto, Julia usa per impostazione predefinita il tipo di elemento Any, ma lo si può definire in modo più specifico annotando l'array vuoto con il tipo di elemento desiderato.
julia> empty_vec = []
Any[]
julia> empty_int_vec = Int64[]
Int64[]
Leggi e ricorda questa regola:
Questo è familiare a chiunque abbia usato altri linguaggi di data science (R, Matlab, Fortran...), ma può sembrare scioccante agli informatici con un background in linguaggi simili al C.
A parte questo, gli indici funzionano come potresti immaginare: basta metterli tra parentesi quadre:
squares = [0, 1, 4, 9, 16]
squares[1] # 0
squares[3] # 4
squares[begin] # 0 ("begin" is synonym for 1)
squares[end] # 16 ("end" is synonym for length(squares))
Nota la comodità di indicizzare con end (molto utile) e con begin (che probabilmente non lo è).
Chi programma in Python potrebbe chiedersi come funzionano gli indici negativi.
In realtà no: non fanno parte di Julia e sollevano un BoundsError, come qualsiasi indice minore di 1 o maggiore di length(squares).
I Vector in Julia sono mutabili: possiamo modificare il contenuto delle singole celle.
julia> vals = [1, 3, 5, 7]
4-element Vector{Int64}:
1
3
5
7
julia> vals[2] = 4 # reassign the value of this element
4
# Only the value at position 2 changes:
julia> vals
4-element Vector{Int64}:
1
4
5
7
Esistono molte funzioni per manipolare i vettori, anche se la documentazione di Julia le generalizza a «collezioni» anziché a Vector.
Nota che, per convenzione, le funzioni che modificano il proprio input hanno un ! nel nome.
Il compilatore non lo impone, ma nel mondo Julia è una convenzione molto forte.
Queste sono alcune delle funzioni più utili:
push!().pop!().pushfirst!() e popfirst!().insert!() e deleteat!().julia> vals = [1, 3]
2-element Vector{Int64}:
1
3
julia> push!(vals, 5, 6) # can add multiple values
4-element Vector{Int64}:
1
3
5
6
julia> pop!(vals) # mutates vals, return popped value
6
julia> vals
3-element Vector{Int64}:
1
3
5
Da aspirante maga, Elyse deve fare pratica con le basi. Ha una pila di carte che vuole manipolare.
Per semplificare un po' le cose, usa solo le carte da 1 a 10, così la sua pila di carte può essere rappresentata da un array di numeri. La posizione di una determinata carta corrisponde all'indice nell'array.
Per pescare una carta, restituisci la carta all'indice position dalla pila data.
julia> stack = [1, 2, 4, 1];
julia> position = 3;
julia> get_item(stack, position)
4
Esegui un gioco di prestigio e scambia la carta all'indice position con la carta sostitutiva fornita.
Restituisci la pila aggiornata.
julia> stack = [1, 2, 4, 1];
julia> position = 3;
julia> replacement_card = 6;
julia> set_item!(stack, position, replacement_card)
[1, 2, 6, 1]
Fai apparire una carta inserendo una nuova carta in cima alla pila. Restituisci la pila aggiornata.
julia> stack = [5, 9, 7, 1];
julia> new_card = 8;
julia> insert_item_at_top!(stack, new_card)
[5, 9, 7, 1, 8]
Fai sparire una carta rimuovendo dalla pila la carta alla position indicata.
Restituisci la pila aggiornata.
julia> stack = [3, 2, 6, 4, 8];
julia> position = 3;
julia> remove_item!(stack, position)
[3, 2, 4, 8]
Fai sparire una carta rimuovendo la carta in cima alla pila. Restituisci la pila aggiornata.
julia> stack = [3, 2, 6, 4, 8];
julia> remove_item_from_top!(stack)
[3, 2, 6, 4]
Fai apparire una carta inserendo una nuova carta in fondo alla pila. Restituisci la pila aggiornata.
julia> stack = [5, 9, 7, 1];
julia> new_card = 8;
julia> insert_item_at_bottom!(stack, new_card)
[8, 5, 9, 7, 1]
Fai sparire una carta rimuovendo la carta in fondo alla pila. Restituisci la pila aggiornata.
julia> stack = [8, 5, 9, 7, 1];
julia> remove_item_at_bottom!(stack)
[5, 9, 7, 1]
Controlla se la dimensione della pila è uguale a stack_size oppure no.
julia> stack = [3, 2, 6, 4, 8];
julia> stack_size = 4;
julia> check_size_of_stack(stack, stack_size)
false
Iscriviti a Exercism per imparare e padroneggiare Julia con 35 concetti128 esercizi e il mentoring di persone reali, tutto gratis.