Uma list em R é uma coleção ordenada de itens, que difere dos vectors em alguns aspetos:
numeric com character).As analogias com outras linguagens são imprecisas.
Uma list de R é um pouco semelhante a um dicionário de Python, mas a list é ordenada e pode ser acedida por índice numérico.
É também algo semelhante a uma struct de C, com a diferença de que a list pode ser facilmente ampliada em tempo de execução.
Atribuir nomes (a que muitas vezes se dá o nome de «etiquetas») aos elementos é mais comum nas listas do que nos vetores:
list(x = 5.3, y = 4.2, color = "blue")
#> $x
#> [1] 5.3
#> $y
#> [1] 4.2
#> $color
#> [1] "blue"
No entanto, as etiquetas são opcionais e, nesse caso, o R usa apenas números de índice:
list(5.3, 4.2, "blue")
#> [[1]]
#> [1] 5.3
#> [[2]]
#> [1] 4.2
#> [[3]]
#> [1] "blue"
Há três formas de o fazer, cada uma útil em contextos diferentes.
$tag
Muito comum se os nomes das etiquetas forem conhecidos de antemão.
point <- list(x = 5.3, y = 4.2, color = "blue")
#> point$x
#> [1] 5.3
#> point$color
#> [1] "blue"
[[tag]]
Tem a vantagem de o nome da etiqueta poder ser escolhido em tempo de execução. Repara nos parênteses retos duplos.
want <- "y"
point[[want]] # same as point$y
#> [1] 4.2
Isto funciona quer a lista tenha etiquetas, quer não. Mais uma vez, os parênteses retos são duplos.
point[[3]] # same as point$color
#> [1] "blue"
É simples: atribuir um valor a um elemento modifica-o se ele existir ou insere-o se for novo.
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, atribui NULL ao elemento que não queres.
point$trust <- NULL
str(point)
#> List of 3
#> $ x : num 5.3
#> $ y : num 4.2
#> $ color: chr "red"
A classe vector é tecnicamente conhecida como atomic vector, porque só pode conter valores atómicos: numeric, character, boolean, etc.
Como uma list pode conter outras listas, também é conhecida como recursive vector.
Além de ser um ponto técnico de nomenclatura, isto serve de lembrete de que as listas podem ter uma estrutura arbitrariamente complexa. É responsabilidade do programador compreender o que será fornecido ao aceder a um elemento de uma lista.
Alguns exemplos acima usaram parênteses retos duplos [[ ]] para aceder a elementos de listas.
Isto tenta achatar o elemento até ao seu tipo subjacente, o que é útil se quiseres apenas um número ou uma string.
Usar parênteses retos simples [ ] não faz esse achatamento, e o valor devolvido será uma sublista.
point[["color"]]
#> [1] "red" # flattened
point["color"]
#> $color
#> [1] "red" # sublist
Mesmo que a sublista não seja o que um programador de R principiante provavelmente quer, tem isso em conta.
Para máxima flexibilidade, muitas funções padrão do R devolvem uma list, mesmo quando esta contém um único valor atómico, como aqui.
Para converter num vetor, há duas possibilidades.
[[1]]
unlist().pt <-point["color"]
pt[[1]]
#> [1] "red" # simple 1-element vector
unlist(pt)
#> color
#> "red" # 1-element vector with name
Tem cuidado com unlist().
Achatar a estrutura é útil neste caso simples, mas pode causar surpresas com elementos de lista mais complicados.
Uma list, tal como um vector atómico, é armazenada de forma contígua. A diferença é que os vetores numéricos e booleanos armazenam valores, mas a lista armazena referências a objetos localizados noutro local da memória.
Saber isto raramente é importante para quem usa R, mas numa comunidade poliglota como o Exercism pode ser útil para programadores familiarizados com outras linguagens.