Un list en R es una colección ordenada de elementos que se diferencia de los vectors en varios aspectos:
numeric con character).Las analogías con otros lenguajes son imprecisas.
Un list de R se parece un poco a un diccionario de Python, pero el list está ordenado y se puede acceder a él mediante un índice numérico.
También se parece un poco a un struct de C, salvo que el list se puede extender fácilmente en tiempo de ejecución.
Dar nombres (a los que a menudo se llama «etiquetas») a los elementos es más frecuente con las listas que con los vectores:
list(x = 5.3, y = 4.2, color = "blue")
#> $x
#> [1] 5.3
#> $y
#> [1] 4.2
#> $color
#> [1] "blue"
Sin embargo, las etiquetas son opcionales y, en ese caso, R simplemente usará números de índice:
list(5.3, 4.2, "blue")
#> [[1]]
#> [1] 5.3
#> [[2]]
#> [1] 4.2
#> [[3]]
#> [1] "blue"
Hay tres formas de hacerlo, y cada una es útil en contextos distintos.
$tag
Es muy común si los nombres de las etiquetas se conocen de antemano.
point <- list(x = 5.3, y = 4.2, color = "blue")
#> point$x
#> [1] 5.3
#> point$color
#> [1] "blue"
[[tag]]
Tiene la ventaja de que el nombre de la etiqueta se puede elegir en tiempo de ejecución. Fíjate en los corchetes dobles.
want <- "y"
point[[want]] # same as point$y
#> [1] 4.2
Funciona tanto si la lista tiene etiquetas como si no. De nuevo, los corchetes van dobles.
point[[3]] # same as point$color
#> [1] "blue"
Sencillo: asignar a un elemento lo modifica si ya existe o lo inserta si es nuevo.
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
Para eliminar, asigna NULL al elemento que ya no quieras.
point$trust <- NULL
str(point)
#> List of 3
#> $ x : num 5.3
#> $ y : num 4.2
#> $ color: chr "red"
La clase vector se conoce técnicamente como atomic vector, porque solo puede contener valores atómicos: numeric, character, boolean, etc.
Como un list puede contener otras listas, también se le conoce como recursive vector.
Además de ser un detalle técnico de nomenclatura, esto nos recuerda que las listas pueden tener una estructura arbitrariamente compleja. Es responsabilidad de quien programa entender qué se obtendrá al acceder a un elemento de la lista.
Algunos de los ejemplos anteriores usaban corchetes dobles [[ ]] para acceder a los elementos de una lista.
Esto intentará aplanar el elemento a su tipo subyacente, lo cual es útil si solo quieres un número o un string.
Usar corchetes simples [ ] no hará ese aplanamiento, y el valor devuelto será una sublista.
point[["color"]]
#> [1] "red" # flattened
point["color"]
#> $color
#> [1] "red" # sublist
Aunque la sublista no sea lo que un programador novato de R probablemente quiera, tenlo presente.
Para lograr la máxima flexibilidad, muchas funciones estándar de R devuelven un list, incluso cuando contiene un solo valor atómico como aquí.
Para convertir a un vector hay dos posibilidades.
[[1]]
unlist().pt <-point["color"]
pt[[1]]
#> [1] "red" # simple 1-element vector
unlist(pt)
#> color
#> "red" # 1-element vector with name
Ten cuidado con unlist().
Aplanar la estructura es útil en este caso sencillo, pero puede dar sorpresas con elementos de lista más complicados.
Un list, al igual que un vector atómico, se almacena de forma contigua. La diferencia es que los vectores numéricos y booleanos almacenan valores, mientras que la lista almacena referencias a objetos que están en otra parte de la memoria.
Saber esto rara vez es importante para quien usa R, pero en una comunidad políglota como Exercism puede ser útil para programadores familiarizados con otros lenguajes.