Оператор доллара как аргумент функции для sapply не работает как ожидалось
У меня есть следующий список
test_list=list(list(a=1,b=2),list(a=3,b=4))
и я хочу извлечь все элементы с именем элемента списка a
.
Я могу сделать это через
sapply(test_list,`[[`,"a")
который дает мне правильный результат
#[1] 1 3
Когда я пробую то же самое с оператором Rs dollar $
, я получаю NULL
sapply(test_list,`$`,"a")
#[[1]]
#NULL
#
#[[2]]
#NULL
Однако, если я использую его в одном элементе test_list
, он работает как ожидалось
`$`(test_list[[1]],"a")
#[1] 1
Я пропустил что-то очевидное здесь?
Ответы
Ответ 1
Из того, что я смог определить, это сочетание двух вещей.
Во-первых, второй элемент $
сопоставляется, но не оценивается, поэтому он не может быть переменной.
Во-вторых, когда аргументы передаются в функции, они назначаются соответствующим переменным в вызове функции. При передаче в sapply
"a"
назначается переменная и поэтому больше не будет работать с $
. Мы видим это, выполняя запуск
sapply("a", print)
[1] "a"
a
"a"
Это может привести к особым результатам, подобным этому
sapply(test_list, function(x, a) {`$`(x, a)})
[1] 1 3
Если несмотря на то, что a
является переменной (которая еще не была назначена) $
соответствует ей именам элементов в списке.
Ответ 2
оценка против none
[[
оценивает свой аргумент, а $
- нет. L[[a]]
получает компонент L
, имя которого хранится в переменной a
. $
просто передает имя аргумента как строку символов, поэтому L$a
находит "a"
компонент L
. a
не рассматривается как переменная, содержащая имя компонента - только символьная строка.
Ниже L[[b]]
возвращает компонент L
с именем "a"
, потому что переменная b
имеет значение "a"
, тогда как L$b
возвращает компонент L
с именем "b"
, потому что с этим синтаксисом b
не рассматривается как переменная, а рассматривается как символьная строка, которая сама передается.
L <- list(a = 1, b = 2)
b <- "a"
L[[b]] # same as L[["a"]] since b holds a
## [1] 1
L$b # same as L[["b"]] since b is regarded as a character string to be passed
## [1] 2
sapply
Теперь, когда мы понимаем ключевое различие bewteen $и [[чтобы посмотреть, что происходит с sapply
, рассмотрим этот пример. Мы сделали каждый элемент test_list
в объект "foo"
и определили наши собственные методы $.foo
и [[.foo
, которые просто показывают, что R передает метод через аргумент name
:
foo_list <- test_list
class(foo_list[[1]]) <- class(foo_list[[2]]) <- "foo"
"$.foo" <- "[[.foo" <- function(x, name) print(name)
result <- sapply(foo_list, "$", "a")
## "..."
## "..."
result2 <- sapply(foo_list, "[[", "a")
## [1] "a"
## [1] "a"
Что происходит в первом случае, так это то, что sapply
вызывает whatever$...
, а ...
не оценивается, поэтому он будет искать компонент списка, который буквально называется "..."
, и, конечно же, существует нет такой компоненты, поэтому whatever$...
равно NULL, следовательно, NULL, показанные на выходе в вопросе. Во втором случае whatever[[[...]]
оценивает whatever[["a"]]
, следовательно, наблюдаемый результат.