Li

Listas em R

1 exercício

Sobre Listas

Uma list em R é uma coleção ordenada de itens, que difere dos vectors em alguns aspetos:

  • Os itens podem ser de tipos diferentes (por exemplo, misturar numeric com character).
  • Os itens podem ser estruturas complexas (por exemplo, vetores, outras listas, etc.).
  • A sintaxe para aceder aos elementos é um pouco diferente.

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.

Criar listas

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"

Aceder aos elementos de uma lista

Há três formas de o fazer, cada uma útil em contextos diferentes.

1. Com a notação $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"

2. Com a notação [[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

3. Com o índice de posição

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"

Adicionar e eliminar elementos

É 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"

As listas são «vetores recursivos»

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.

Mais sobre a indexação de listas

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. Extrair o primeiro elemento com [[1]]
  2. Usar a função 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.

Advanced

Representação interna

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.

Editar via GitHub A ligação abre numa nova janela ou separador

Aprende Listas