假设我有一个列表,说它有三个级别:
tmp =list(list(list(c(2,9,10), NULL), c(1,3,4,6)), 7)
Run Code Online (Sandbox Code Playgroud)
这会输出
[[1]]
[[1]][[1]]
[[1]][[1]][[1]]
[1] 2 9 10
[[1]][[1]][[2]]
NULL
[[1]][[2]]
[1] 1 3 4 6
[[2]]
[1] 7
Run Code Online (Sandbox Code Playgroud)
我想删除NULL元素和列表的本地级别.即,嵌套列表tmp只有2个级别,它就变成了
tmp =list(list(c(2,9,10), c(1,3,4,6)), 7).
Run Code Online (Sandbox Code Playgroud)
也就是说,所需的输出可能如下:
tmp
[[1]]
[[1]][[1]]
[1] 2 9 10
[[1]][[2]]
[1] 1 3 4 6
[[2]]
[1] 7
Run Code Online (Sandbox Code Playgroud)
我试图搜索NULL的索引位置,但没有运气.此外,我不知道如何检测和取消列表列表中包含NULL元素的列表.谢谢!
Bea*_*eld 16
通常,您使用删除NULL平面列表中的元素
ll <- list( 1, 2, NULL, 3 )
ll <- ll[ ! sapply(ll, is.null) ]
Run Code Online (Sandbox Code Playgroud)
如果您事先不知道结构,那么将此解决方案与递归函数相结合是一个明显的例子:
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
Run Code Online (Sandbox Code Playgroud)
编辑
尽可能简单地重新解决问题总是好的.我从你的评论中理解的是,NULL你想要替换孩子本身只包含一个孩子的每个元素(独立于元素的出现).还有另一个案例需要考虑:两个兄弟叶子也可以NULL.所以让我们从一个更复杂的例子开始:

tree <- list(
list(
list(
list(
list( NULL, NULL ),
list( NULL, NULL )
),
7
),
list(
list(
list( c(1,2), NULL ),
c(3,4)
))))
Run Code Online (Sandbox Code Playgroud)
通过应用递归方法,当然也解决了使树平坦化的这个孤立问题:
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) )
Run Code Online (Sandbox Code Playgroud)
当然,您可以直接组合这两个函数,以避免对堆栈施加两次压力:
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 )
Run Code Online (Sandbox Code Playgroud)