Una list in R è una collezione ordinata di elementi e si differenzia dai vectors per alcuni aspetti:
numeric e character).Le analogie con altri linguaggi sono imprecise.
Una list di R assomiglia in parte a un dizionario di Python, ma è ordinata e si può accedere ai suoi elementi tramite un indice numerico.
Assomiglia anche a una struct del C, con la differenza che una list si può estendere facilmente in fase di esecuzione.
Assegnare dei nomi (spesso chiamati «tag») agli elementi è più comune con le liste che con i vettori:
list(x = 5.3, y = 4.2, color = "blue")
#> $x
#> [1] 5.3
#> $y
#> [1] 4.2
#> $color
#> [1] "blue"
Tuttavia, i tag sono facoltativi e in quel caso R usa semplicemente i numeri dell'indice:
list(5.3, 4.2, "blue")
#> [[1]]
#> [1] 5.3
#> [[2]]
#> [1] 4.2
#> [[3]]
#> [1] "blue"
Ci sono tre modi per farlo, ognuno utile in contesti diversi.
$tag
Molto comune se i nomi dei tag sono noti in anticipo.
point <- list(x = 5.3, y = 4.2, color = "blue")
#> point$x
#> [1] 5.3
#> point$color
#> [1] "blue"
[[tag]]
Questo ha il vantaggio che il nome del tag può essere scelto in fase di esecuzione. Nota le doppie parentesi quadre.
want <- "y"
point[[want]] # same as point$y
#> [1] 4.2
Funziona sia che la lista abbia dei tag, sia che non ne abbia. Anche qui le parentesi quadre sono doppie.
point[[3]] # same as point$color
#> [1] "blue"
Semplice: assegnare un valore a un elemento lo modifica se esiste, oppure lo inserisce se è nuovo.
point$color <- "red"
point$trust <- TRUE
# str() gives more compact output than the default display
str(point)
#> List of 4
#> $ x : num 5.3
#> $ y : num 4.2
#> $ color: chr "red"
#> $ trust: logi TRUE
Per eliminarlo, assegna NULL all'elemento che non vuoi più.
point$trust <- NULL
str(point)
#> List of 3
#> $ x : num 5.3
#> $ y : num 4.2
#> $ color: chr "red"
La classe vector è tecnicamente nota come atomic vector, perché può contenere solo valori atomici: numeric, character, boolean, ecc.
Poiché una list può contenere altre liste, è anche nota come recursive vector.
Oltre a essere una questione di nomenclatura, questo ci ricorda che le liste possono avere una struttura complessa a piacere. È responsabilità del programmatore capire cosa verrà restituito quando si accede a un elemento della lista.
Alcuni esempi precedenti usavano le doppie parentesi quadre [[ ]] per accedere agli elementi di una lista.
Questo cerca di appiattire l'elemento al suo tipo di base: è utile se vuoi semplicemente un numero o una stringa.
Usando le parentesi quadre singole [ ] questo appiattimento non avviene e il valore restituito sarà una sottolista.
point[["color"]]
#> [1] "red" # flattened
point["color"]
#> $color
#> [1] "red" # sublist
Anche se la sottolista non è ciò che probabilmente vuole chi muove i primi passi in R, tienilo comunque presente.
Per garantire la massima flessibilità, molte funzioni standard di R restituiscono una list, anche quando contiene un unico valore atomico come in questo caso.
Per convertire il risultato in un vettore ci sono due possibilità.
[[1]]
unlist().pt <-point["color"]
pt[[1]]
#> [1] "red" # simple 1-element vector
unlist(pt)
#> color
#> "red" # 1-element vector with name
Fai attenzione con unlist().
Appiattire la struttura è utile in questo caso semplice, ma può riservare sorprese con elementi di lista più complessi.
Una list, come un vector atomico, è memorizzata in modo contiguo. La differenza è che i vettori numerici e booleani memorizzano valori, mentre la lista memorizza riferimenti a oggetti che si trovano altrove in memoria.
Sapere questo è raramente importante per chi usa R, ma in una comunità poliglotta come Exercism può essere utile a chi ha familiarità con altri linguaggi.