美元运算符作为函数参数,因为sapply没有按预期工作

时间:2015-12-31 10:21:19

标签: r lapply sapply dollar-sign

我有以下列表

test_list=list(list(a=1,b=2),list(a=3,b=4))

我希望提取列表元素名称为a的所有元素。

我可以通过

来做到这一点
sapply(test_list,`[[`,"a")

给了我正确的结果

#[1] 1 3

当我尝试使用Rs美元运算符$时,我得到NULL

sapply(test_list,`$`,"a")
#[[1]]
#NULL
#
#[[2]]
#NULL

但是,如果我在test_list的单个元素上使用它,它会按预期工作

`$`(test_list[[1]],"a")
#[1] 1

我错过了一些明显的东西吗?

2 个答案:

答案 0 :(得分:11)

评估与无

[[评估其参数,而$则不。 L[[a]]获取L的组件,其名称保存在变量a中。 $只是将参数名称本身作为字符串传递,因此L$a会找到"a"的{​​{1}}组件。 L不被视为包含组件名称的变量 - 只是一个字符串。

a下方L[[b]]返回名为L的{​​{1}}组件,因为变量"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

现在我们了解了$和[[看看sapply正在发生什么的关键区别)。我们已将test_list的每个元素转换为"foo"个对象,并定义了我们自己的$.foo[[.foo方法,这些方法只显示R通过{{1}传递给方法的内容参数:

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$...未被评估,因此它将寻找一个名为{{1}的列表组件当然,没有这样的组件,因此...为NULL,因此在问题的输出中显示了NULL。在第二种情况下,"..."评估为whatever$...因此观察到的结果。

答案 1 :(得分:6)

从我能够确定它是两件事的组合。

首先,the second element of $ is matched but not evaluated so it cannot be a variable

其次,当参数传递给函数时,它们被赋值给函数调用中的相应变量。传递给sapply "a"时,会将其分配给变量,因此不再使用$。我们可以通过运行

来看到这一点
sapply("a", print)
[1] "a"
  a 
"a"

这可能导致像这样的特殊结果

sapply(test_list, function(x, a) {`$`(x, a)})
[1] 1 3

尽管a是一个变量(甚至没有分配)$将其与列表中元素的名称相匹配。