Une list en R est une collection ordonnée d'éléments, qui se distingue des vectors de plusieurs façons :
numeric avec des character).Les analogies avec d'autres langages sont imparfaites.
Une list en R ressemble un peu à un dictionnaire Python, mais la list est ordonnée et on peut y accéder par un indice numérique.
Elle ressemble aussi un peu à une struct du C, à ceci près qu'on peut facilement étendre la list à l'exécution.
Donner des noms (souvent appelés « tags ») aux éléments est plus courant avec les listes qu'avec les vecteurs :
list(x = 5.3, y = 4.2, color = "blue")
#> $x
#> [1] 5.3
#> $y
#> [1] 4.2
#> $color
#> [1] "blue"
Cependant, les tags sont facultatifs, et R se contente alors d'utiliser des numéros d'indice :
list(5.3, 4.2, "blue")
#> [[1]]
#> [1] 5.3
#> [[2]]
#> [1] 4.2
#> [[3]]
#> [1] "blue"
Il y a trois façons de faire, chacune utile dans des contextes différents.
$tag
Très courant si les noms des tags sont connus à l'avance.
point <- list(x = 5.3, y = 4.2, color = "blue")
#> point$x
#> [1] 5.3
#> point$color
#> [1] "blue"
[[tag]]
Cela a l'avantage de permettre de choisir le nom du tag à l'exécution. Remarque les doubles crochets.
want <- "y"
point[[want]] # same as point$y
#> [1] 4.2
Cela fonctionne que la liste ait des tags ou non. Là encore, les crochets sont doublés.
point[[3]] # same as point$color
#> [1] "blue"
C'est simple : affecter une valeur à un élément le modifie s'il existe, ou l'insère s'il est nouveau.
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
Pour supprimer un élément dont on ne veut plus, il suffit de lui affecter NULL.
point$trust <- NULL
str(point)
#> List of 3
#> $ x : num 5.3
#> $ y : num 4.2
#> $ color: chr "red"
La classe vector est techniquement appelée atomic vector, car elle ne peut contenir que des valeurs atomiques : numeric, character, boolean, etc.
Comme une list peut contenir d'autres listes, on l'appelle aussi recursive vector.
En plus d'être un point de nomenclature technique, cela rappelle que les listes peuvent avoir une structure arbitrairement complexe. Il incombe au programmeur ou à la programmeuse de comprendre ce qui sera fourni lorsqu'on accède à un élément de la liste.
Certains exemples ci-dessus utilisent des doubles crochets [[ ]] pour accéder aux éléments d'une liste.
Cela tente d'aplatir l'élément vers son type sous-jacent, ce qui est utile si tu veux simplement un nombre ou une string.
Avec des crochets simples [ ], cet aplatissement n'a pas lieu : la valeur renvoyée est une sous-liste.
point[["color"]]
#> [1] "red" # flattened
point["color"]
#> $color
#> [1] "red" # sublist
Même si la sous-liste n'est pas ce qu'un programmeur R débutant souhaite probablement, il faut en être conscient.
Pour une souplesse maximale, de nombreuses fonctions standard de R renvoient une list, même lorsqu'elle ne contient qu'une seule valeur atomique comme ici.
Pour convertir en vecteur, il y a deux possibilités.
[[1]]
unlist().pt <-point["color"]
pt[[1]]
#> [1] "red" # simple 1-element vector
unlist(pt)
#> color
#> "red" # 1-element vector with name
Fais attention avec unlist().
Aplatir la structure est utile dans ce cas simple, mais peut réserver des surprises avec des éléments de liste plus compliqués.
Une list, comme un vector atomique, est stockée de manière contiguë. La différence est que les vecteurs numériques et booléens stockent des valeurs, tandis que la liste stocke des références vers des objets situés ailleurs en mémoire.
Savoir cela est rarement important pour une personne qui utilise R, mais dans une communauté polyglotte comme Exercism, cela peut être utile aux programmeurs qui connaissent d'autres langages.