通常,您会删除平面列表中的 NULL 元素
ll <- list( 1, 2, NULL, 3 )
ll <- ll[ ! sapply(ll, is.null) ]
如果你事先不知道结构,这是一个将这个解决方案与递归函数结合起来的明显案例:
removeNullRec <- function( x ){
x <- x[ !sapply( x, is.null ) ]
if( is.list(x) ){
x <- lapply( x, removeNullRec)
}
return(x)
}
removeNullRec(tmp)
[[1]]
[[1]][[1]]
[[1]][[1]][[1]]
[1] 2 9 10
[[1]][[2]]
[1] 1 3 4 6
[[2]]
[1] 7
编辑
尽可能简单地重新表述问题总是好的。我从您的 cmets 了解到的是,(与 NULL 元素的出现无关)您希望将每个仅包含一个子元素的元素替换为子元素本身。还有另一种情况需要考虑:两个兄弟叶子也可以是NULL。所以让我们从一个稍微复杂一点的例子开始:
tree <- list(
list(
list(
list(
list( NULL, NULL ),
list( NULL, NULL )
),
7
),
list(
list(
list( c(1,2), NULL ),
c(3,4)
))))
这个孤立的树扁平化问题当然也可以通过应用递归方法得到最好的解决:
flatTreeRec <- function( x ){
if( is.list(x) ){
# recursion
x <- lapply( x, flatTree )
# remove empty branches
x <- x[ sapply( x, length ) > 0 ]
# flat branches with only child
if( length(x) == 1 ){
x <- x[[1]]
}
}
return(x)
}
flatTreeRec( removeNullRec(tree) )
当然你也可以直接将这两个函数结合起来,避免两次给你的堆栈带来压力:
removeNullAndFlatTreeRec <- function( x ){
x <- x[ !sapply( x, is.null ) ]
if( is.list(x) ){
x <- lapply( x, removeNullRec)
x <- x[ sapply( x, length ) > 0 ]
if( length(x) == 1 ){
x <- x[[1]]
}
}
return(x)
}
removeNullAndFlatTreeRec( tree )