Uma list em R é uma coleção ordenada de itens, que difere dos vectors em alguns aspectos:
numeric com character).Analogias com outras linguagens são imprecisas.
Uma list de R é um pouco parecida com um dicionário do Python, mas a list é ordenada e pode ser acessada por índice numérico.
É um pouco parecida com um struct de C, exceto que a list pode ser facilmente estendida em tempo de execução.
Dar nomes (muitas vezes chamados de "tags") aos elementos é mais comum com listas do que com vetores:
list(x = 5.3, y = 4.2, color = "blue")
#> $x
#> [1] 5.3
#> $y
#> [1] 4.2
#> $color
#> [1] "blue"
No entanto, as tags são opcionais e, nesse caso, 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 fazer isso, cada uma útil em contextos diferentes.
$tag
Muito comum quando os nomes das tags são conhecidos de antemão.
point <- list(x = 5.3, y = 4.2, color = "blue")
#> point$x
#> [1] 5.3
#> point$color
#> [1] "blue"
[[tag]]
Isso tem a vantagem de permitir escolher o nome da tag em tempo de execução. Repare nos colchetes duplos.
want <- "y"
point[[want]] # same as point$y
#> [1] 4.2
Isso funciona com ou sem tags na lista. Novamente, os colchetes são duplos.
point[[3]] # same as point$color
#> [1] "blue"
Simples: atribuir a um elemento modifica se ele já existe, ou insere 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 remover, atribua NULL ao elemento indesejado.
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, ela também é conhecida como recursive vector.
Além de ser um ponto técnico de nomenclatura, isso serve de lembrete de que as listas podem ter uma estrutura arbitrariamente complexa. É responsabilidade de quem programa entender o que será fornecido ao acessar um elemento da lista.
Alguns exemplos acima usaram colchetes duplos [[ ]] para acessar elementos da lista.
Isso tenta achatar o elemento para o seu tipo subjacente, o que é útil quando você quer apenas um número ou uma string.
Usar colchetes simples [ ] não faz esse achatamento, e o valor retornado 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 iniciante em R provavelmente quer, é bom estar ciente disso.
Para máxima flexibilidade, muitas funções padrão de R retornam uma list, mesmo quando ela contém um único valor atômico, como aqui.
Há duas possibilidades para converter em vetor.
[[1]]
unlist().pt <-point["color"]
pt[[1]]
#> [1] "red" # simple 1-element vector
unlist(pt)
#> color
#> "red" # 1-element vector with name
Cuidado com unlist().
Achatar a estrutura é útil nesse caso simples, mas pode causar surpresas com elementos de lista mais complicados.
Uma list, assim como um vector atômico, é armazenada de forma contígua. A diferença é que vetores numéricos e Boolean armazenam valores, enquanto a lista armazena referências a objetos localizados em outro lugar da memória.
Saber disso raramente é importante para quem usa R, mas em uma comunidade poliglota como o Exercism pode ser útil para programadores familiarizados com outras linguagens.