有人可以向我解释为什么使用 purrr 会出错吗:
map(list(list(a=1, b=2, c=3), list(a=1, b=2, c=3)), `[[<-`, "b", 1)
但与 lapply 的相同调用似乎有效。
我的印象是[[<-
只是一个函数调用,所以期望 purrr 和 lapply 在这里做同样的事情。
最佳答案
问题出在purrr::as_mapper()
,这map()
在引擎盖下调用。考虑差异:
x <- list( a=1, b=2, c=3 )
`[[<-`( x, "b", 1 ) # This is what lapply() calls
# x is unchanged, returns modified list
purrr::as_mapper(`[[<-`)( x, "b", 1 ) # This is what map() calls
# x is modified in-place, returns value 1
第二个函数调用的行为就像您键入以下赋值表达式一样:
(x[["b"]] <- 1)
# [1] 1
当函数向下传递给 map()
时,这肯定会导致问题内部结构。有趣的是,用 ~
包装函数lambda 有效,但返回“错误”结果:
y <- list(list(a=1, b=2, c=3), list(a=1, b=2, c=3))
purrr::map( y, ~purrr::as_mapper(`[[<-`)(.x, "b", 1) )
# [[1]]
# [1] 1
# [[2]]
# [1] 1
purrr::map( y, purrr::as_mapper(`[[<-`), "b", 1 )
# Error in list(a = 1, b = 2, c = 3)[["b"]] <- 1 :
# target of assignment expands to non-language object
正确的purrr
相当于你的 lapply()
例子看起来像这样:
r1 <- lapply(y, `[[<-`, "b", 1)
r2 <- purrr::map(y, purrr::modify_at, "b", ~1)
r3 <- purrr::map(y, ~`[[<-`(.x, "b", 1))
identical( r1, r2 ) # TRUE
identical( r1, r3 ) # TRUE
在上面,modify_at()
返回修改后的列表,就像 [[<-(...)
确实如此,波浪号 ~
需要因为 modify_at()
期望一个函数。另一种方法是包装 `[[<-`
进入 ~
lambda 。
关于r - 用 [[<-,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62160525/