在 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"
)。
我正在努力填充预定义的 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"
)。