美元运算符作为 sapply 的函数参数未按预期工作

Dollar operator as function argument for sapply not working as expected

我有以下列表

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

我是不是漏掉了什么明显的东西?

据我所知,这是两件事的结合。

第一,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 是一个变量(甚至还没有被赋值),$ 将它与列表中元素的名称相匹配。

评价对比none

[[ 计算其参数,而 $ 不计算。 L[[a]] 获取 L 的组件,其名称保存在变量 a 中。 $ 只是将参数名称本身作为字符串传递,因此 L$a 找到了 L"a" 组件。 a 不被视为保存组件名称的变量 -- 只是一个字符串。

L[[b]] returns 下面 L 的组件命名为 "a" 因为变量 b 的值为 "a"L$b returns 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 是怎么回事,请考虑这个例子。我们已经将 test_list 的每个元素都变成了一个 "foo" 对象,并定义了我们自己的 $.foo[[.foo 方法,这些方法简单地显示了 R 通过 [=36 传递给方法的内容=] 参数:

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