将嵌套环境转换为嵌套列表

时间:2014-03-26 23:15:45

标签: r list recursion environment

我真的觉得我错过了一些完全显而易见的东西,但我无法指责它:我如何将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>

这里的诀窍是什么?

1 个答案:

答案 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),您应该问问自己为什么会获得无限递归。