Краткая справка: Многие (большинство?) Современные языки программирования, которые широко распространены, имеют по крайней мере несколько общих ADT [абстрактных типов данных], в частности,
строка (последовательность, состоящая из символов)
список (упорядоченный набор значений) и
тип на основе карты (неупорядоченный массив, который сопоставляет ключи со значениями)
В языке программирования R первые два реализованы как character
и vector
соответственно.
Когда я начал изучать R, с самого начала были очевидны две вещи: list
- самый важный тип данных в R (потому что это родительский класс для R data.frame
), а во-вторых, я просто не мог Я не понимаю, как они работают, по крайней мере, недостаточно хорошо, чтобы правильно использовать их в моем коде.
Во-первых, мне показалось, что тип данных R's list
является простой реализацией карты ADT (dictionary
в Python, NSMutableDictionary
в Objective C, hash
в Perl и Ruby, object literal
в Javascript и т. д.).
Например, вы создаете их так же, как словарь Python, передавая пары ключ-значение в конструктор (который в Python равен dict
, а не list
):
x = list("ev1"=10, "ev2"=15, "rv"="Group 1")
И вы получаете доступ к элементам R List точно так же, как к элементам словаря Python, например, x['ev1']
. Аналогично, вы можете получить только 'keys' или только 'values' по:
names(x) # fetch just the 'keys' of an R list
# [1] "ev1" "ev2" "rv"
unlist(x) # fetch just the 'values' of an R list
# ev1 ev2 rv
# "10" "15" "Group 1"
x = list("a"=6, "b"=9, "c"=3)
sum(unlist(x))
# [1] 18
, но R list
также в отличие от других ADT типа карты (из всех языков, которые я изучал в любом случае). Я предполагаю, что это является следствием первоначальной спецификации для S, то есть намерения разработать DSL для данных / статистики с нуля.
три существенные различия между R list
s и типами отображения в других языках в широком использовании (например, Python, Perl, JavaScript):
first , list
s в R представляют собой упорядоченную коллекцию , точно так же как векторы, даже если значения являются ключами (т. Е. Ключи могут быть любыми хешируемыми последовательные целые числа). Почти всегда тип данных отображения в других языках: неупорядоченный .
second , list
s могут быть возвращены из функций, даже если вы никогда не передавали list
, когда вы вызывали функцию, и , даже если функция, которая возвратила list
не содержит (явный) конструктор list
(Конечно, на практике вы можете справиться с этим, обернув возвращаемый результат в вызов unlist
):
x = strsplit(LETTERS[1:10], "") # passing in an object of type 'character'
class(x) # returns 'list', not a vector of length 2
# [1] list
A третья особенность R list
s: не похоже, что они могут быть членами другого ADT, и если вы попытаетесь это сделать, то основной контейнер будет приведен к list
. Например.,
x = c(0.5, 0.8, 0.23, list(0.5, 0.2, 0.9), recursive=TRUE)
class(x)
# [1] list
Мое намерение здесь не в том, чтобы критиковать язык или то, как он задокументирован; аналогично, я не предполагаю, что с структурой данных list
или ее поведением что-то не так. Все, что мне нужно, это исправить, это мое понимание того, как они работают, чтобы я мог правильно использовать их в своем коде.
Вот некоторые вещи, которые я бы хотел лучше понять:
Какие правила определяют, когда вызов функции вернет list
(например, выражение strsplit
, приведенное выше)?
Если я не назначаю имена явно для list
(например, list(10,20,30,40)
), являются ли имена по умолчанию просто последовательными целыми числами, начинающимися с 1? (Я предполагаю, но я далеко не уверен, что ответ - да, иначе мы не смогли бы привести этот тип list
к вектору с вызовом unlist
.)
Почему эти два разных оператора, []
и [[]]
, возвращают одинаковый результат?
x = list(1, 2, 3, 4)
оба выражения возвращают "1":
x[1]
x[[1]]
почему эти два выражения не возвращают одинаковый результат?
x = list(1, 2, 3, 4)
x2 = list(1:4)
Пожалуйста, не указывайте мне на документацию R (?list
, R-intro
) - я внимательно прочитал, и это не помогает мне ответить на тип вопросов, которые я изложил чуть выше.
(наконец, недавно я узнал и начал использовать пакет R (доступный в CRAN) под названием hash
, который реализует обычное поведение типа карты через класс S4; I могу, конечно, рекомендовать этот пакет.)