list у R - це впорядкована колекція елементів, яка відрізняється від vectors кількома особливостями:
numeric з character).Аналогії з іншими мовами неточні.
list у R дещо схожий на словник у Python, але він упорядкований, і доступ до нього можна отримати за числовим індексом.
Він також дещо схожий на struct у C, але list можна легко розширити під час виконання.
Давати елементам імена (їх часто називають «тегами») у списках доводиться частіше, ніж у векторах:
list(x = 5.3, y = 4.2, color = "blue")
#> $x
#> [1] 5.3
#> $y
#> [1] 4.2
#> $color
#> [1] "blue"
Однак теги необовʼязкові, і тоді R просто використає порядкові номери:
list(5.3, 4.2, "blue")
#> [[1]]
#> [1] 5.3
#> [[2]]
#> [1] 4.2
#> [[3]]
#> [1] "blue"
Є три способи це зробити, і кожен із них зручний у різних ситуаціях.
$tag
Дуже поширений, якщо назви тегів відомі заздалегідь.
point <- list(x = 5.3, y = 4.2, color = "blue")
#> point$x
#> [1] 5.3
#> point$color
#> [1] "blue"
[[tag]]
Його перевага в тому, що назву тега можна вибрати під час виконання. Звернімо увагу на подвійні дужки.
want <- "y"
point[[want]] # same as point$y
#> [1] 4.2
Це працює незалежно від того, чи має список теги. Тут також подвійні дужки.
point[[3]] # same as point$color
#> [1] "blue"
Усе просто: присвоєння елементу змінить його, якщо він існує, або додасть, якщо він новий.
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
Щоб видалити елемент, присвоймо NULL непотрібному елементу.
point$trust <- NULL
str(point)
#> List of 3
#> $ x : num 5.3
#> $ y : num 4.2
#> $ color: chr "red"
Клас vector технічно називають atomic vector, бо він може містити лише атомарні значення: numeric, character, boolean тощо.
Оскільки list може містити інші списки, його ще називають recursive vector.
Окрім суто термінологічного нюансу, це нагадування про те, що списки можуть мати довільно складну структуру. Відповідальність програміста - розуміти, що саме буде надано під час доступу до елемента списку.
У деяких прикладах вище для доступу до елементів списку використано подвійні дужки [[ ]].
Це намагається звести елемент до його базового типу, що зручно, якщо потрібне просто число або рядок тексту (англ. string).
Одинарні дужки [ ] такого зведення не роблять, і повернене значення буде підсписком.
point[["color"]]
#> [1] "red" # flattened
point["color"]
#> $color
#> [1] "red" # sublist
Навіть якщо підсписок - не те, чого, найімовірніше, хоче програміст-початківець у R, варто про це знати.
Задля максимальної гнучкості багато стандартних функцій R повертають list, навіть коли він містить єдине атомарне значення, як тут.
Щоб перетворити його на вектор, є два варіанти.
[[1]]
unlist().pt <-point["color"]
pt[[1]]
#> [1] "red" # simple 1-element vector
unlist(pt)
#> color
#> "red" # 1-element vector with name
Будьмо обережні з unlist().
Зведення структури корисне в цьому простому випадку, але може спричинити несподіванки зі складнішими елементами списку.
list, як і атомарний vector, зберігається неперервно. Різниця в тому, що числові та булеві вектори зберігають значення, а список зберігає посилання на обʼєкти, розташовані в інших ділянках памʼяті.
Знання цього рідко буває важливим для користувача R, але в такій багатомовній спільноті, як Exercism, воно може стати в пригоді програмістам, знайомим з іншими мовами.