在 R 中用 lapply 递归填充列表

Populate list recursively with lapply in R

我正在努力填充预定义的 3 级嵌套列表。

lst <- lapply(list("A1"=NULL, "B1"=NULL),
              function(x){
                 lapply(list("Level2"=NULL),
                        function(y){
                            list("Level3"=NULL)})})

str(lst)
List of 2
 $ A1:List of 1
  ..$ Level2:List of 1
  .. ..$ Level3: NULL
 $ B1:List of 1
  ..$ Level2:List of 1
  .. ..$ Level3: NULL

现在,假设我们想通过连接父级别的名称来替换每第 3 个级别,以获得:

str(lst)
List of 2
 $ A1:List of 1
  ..$ Level2:List of 1
  .. ..$ Level3: "A1///Level2"
 $ B1:List of 1
  ..$ Level2:List of 1
  .. ..$ Level3: "B1///Level2"

按如下方式删除第 2 级名称并打乱初始列表结构:

lst[] <- lapply(names(lst),
                function(x){
                    lapply(names(lst[[x]]),
                           function(y){
                               lst[[x]][[y]][["Level3"]] <- paste(x, y, sep="///")
                           }
                    )
                }
         )

str(lst)
List of 2
 $ A1:List of 1
  ..$ : chr "A1///Level2"
 $ B1:List of 1
  ..$ : chr "B1///Level2"

我很确定这是一项基本任务,但我不明白为什么它不起作用。

您已将第二级列表的元素 Level3 替换为一个字符向量,该向量曾经是一个列表。

要解决这个问题,只需将 paste 函数包装在 list:

此外,在对象名称上使用 lapply 的问题在于结果未命名为原始对象。您可以使用基础 R 中的 setNames 来解决这个问题,但不幸的是,您必须在每个级别都这样做:

lst <- setNames(lapply(names(lst),
                function(x){
                    setNames(lapply(names(lst[[x]]),
                           function(y){
                               setNames(lst[[x]][[y]][["Level3"]] <- list(paste(x, y, sep="///")), "Level3")
                           }
                    ), names(lst[[x]]))
                }
         ), names(lst))
str(lst)
#List of 2
# $ A1:List of 1
#  ..$ Level2:List of 1
#  .. ..$ Level3: chr "A1///Level2"
# $ B1:List of 1
#  ..$ Level2:List of 1
#  .. ..$ Level3: chr "B1///Level2"

您还可以在 rrapply 包中使用 rrapply(基础 rapply 的扩展版本),这可能更容易推广到任意嵌套列表:

library(rrapply)

rrapply(
  lst, 
  f = function(x, .xpos) paste(names(lst)[.xpos[1]], names(lst[[.xpos[1]]])[.xpos[2]], sep = "///")
)
#> $A1
#> $A1$Level2
#> $A1$Level2$Level3
#> [1] "A1///Level2"
#> 
#> 
#> 
#> $B1
#> $B1$Level2
#> $B1$Level2$Level3
#> [1] "B1///Level2"

此处,.xpos 变量求值为当前正在求值的节点在嵌套列表中的位置,因此该信息可用于检索所有祖先节点的名称。

注意返回的结果,默认是how = "replace",会保持原来的list结构,(base rapply默认是how = "unlist")。