【发布时间】:2018-12-07 08:45:26
【问题描述】:
考虑这样一个案例:
xml_list <- list(
a = "7",
b = list("8"),
c = list(
c.a = "7",
c.b = list("8"),
c.c = list("9", "10"),
c.d = c("11", "12", "13")),
d = c("a", "b", "c"))
我正在寻找的是一种如何递归简化此构造的方法,以便在任何长度为 1 的 list 上调用 unlist。上述示例的预期结果如下所示:
list(
a = "7",
b = "8",
c = list(
c.a = "7",
c.b = "8",
c.c = list("9", "10"),
c.d = c("11", "12", "13")),
d = c("a", "b", "c"))
我已经涉足rapply,但它明确地作用于list-成员本身是不列表,所以写了以下内容:
library(magrittr)
clean_up_list <- function(xml_list){
xml_list %>%
lapply(
function(x){
if(is.list(x)){
if(length(x) == 1){
x %<>%
unlist()
} else {
x %<>%
clean_up_list()
}
}
return(x)
})
}
但是,我什至无法测试 Error: C stack usage 7969588 is too close to the limit(至少在我最终想要处理的列表上)。
深入挖掘(在仔细考虑@Roland 的回复之后),我想出了一个利用purrr-goodness 的解决方案,反向迭代列表深度并且几乎 做我想做的事:
clean_up_list <- function(xml_list)
{
list_depth <- xml_list %>%
purrr::vec_depth()
for(dl in rev(sequence(list_depth)))
{
xml_list %<>%
purrr::modify_depth(
.depth = dl,
.ragged = TRUE,
.f = function(x)
{
if(is.list(x) && length(x) == 1 && length(x[[1]]) == 1)
{
unlist(x, use.names = FALSE)
} else {
x
}
})
}
return(xml_list)
}
这似乎可以按预期工作,即使对于我正在处理的深度列表 BUT 曾经是向量的元素(如示例中的 c.d 和 d)现在都已转换到lists,这违背了目的……还有什么进一步的见解吗?
【问题讨论】: