我真的觉得我错过了一些完全显而易见的东西,但我无法指责它:我如何将rapply()
和as.list()
或eapply()
或两者都是为了递归将嵌套的environment
转换为嵌套的list
。
我实际上追求的是类似as.list(<env>, recursive=TRUE)
的东西,我认为rapply()
在某种程度上对此有用。
这是嵌套环境:
env <- new.env()
env$world <- new.env()
env$world$europe <- new.env()
env$world$europe$germany <- new.env()
env$world$europe$germany$foo <- 1
env$world$europe$germany$bar <- 2
这是我最终想要的结构:
env.as.list <- list(
world=list(europe=list(germany=list(foo=1, bar=2)))
)
> env.as.list
$world
$world$europe
$world$europe$germany
$world$europe$germany$foo
[1] 1
$world$europe$germany$bar
[1] 2
而不是基于lapply()
构建一些缓慢的递归函数,我想在.Internal()
中使用快速rapply()
函数。
但由于rapply
适用于lists
,当然它会在遇到environment
后“停止”:
> rapply(as.list(env), as.list, how="list")
$world
$world$europe
<environment: 0x000000001748d640>
这里的诀窍是什么?
答案 0 :(得分:4)
rapply
仅适用于嵌套列表;使用递归。
nested_env_list <- function(env) {
out <- as.list(env)
lapply(out, function(x) if (is.environment(x)) nested_env_list(x) else x)
}
示例:
> env <- new.env(); env$a <- new.env(); env$a$b <- 1; env$a$c <- 2; env$d <- 4
> dput(nested_env_list(env))
structure(list(a = structure(list(b = 1, c = 2), .Names = c("b", "c")), d = 4), .Names = c("a", "d"))
as.list
:您还可以替换as.list
的行为,以确保在将环境传递到as.list
时始终发生这种情况。
as.list.environment <- function(env) {
out <- base::as.list.environment(env)
lapply(out, function(x) if (is.environment(x)) as.list(x) else x)
}
然后R将自动计算出所有未来环境。如果您想在几个选定位置使用旧行为,请明确使用base::as.list.environment
。
例如:
> env <- new.env(); env$a <- new.env(); env$a$b <- 1; env$a$c <- 2; env$d <- 4
> dput(as.list(env))
structure(list(a = structure(list(b = 1, c = 2), .Names = c("b", "c")), d = 4), .Names = c("a", "d"))
最后,如果您将上面的out <- base::as.list.environment(env)
替换为out <- base::as.list(env)
,您应该问问自己为什么会获得无限递归。