从列表列表中删除NULL元素

Chr*_*ris 33 null r list

如何从R中的列表列表中删除null元素,如下所示:

lll <- list(list(NULL),list(1),list("a"))
Run Code Online (Sandbox Code Playgroud)

我想要的对象看起来像:

lll <- list(list(1),list("a"))
Run Code Online (Sandbox Code Playgroud)

我在这里看到了类似的答案:如何从列表中删除元素?但无法将其从简单列表扩展到列表列表.

编辑

我上面的错误例子.这两个答案都适用于更简单的案例(上图).如果列表如下:

lll <- list(list(NULL),list(1,2,3),list("a","b","c"))
Run Code Online (Sandbox Code Playgroud)

如何获得:

lll <- list(list(1,2,3),list("a","b","c"))
Run Code Online (Sandbox Code Playgroud)

Jos*_*ien 26

这种递归解决方案具有处理更深层嵌套列表的优点.

它与Gabor Grothendieck对这个非常相似的问题的答案密切相关.如果函数还要删除您想要的对象list(NULL)(不相同NULL),则需要修改该代码.

## A helper function that tests whether an object is either NULL _or_ 
## a list of NULLs
is.NullOb <- function(x) is.null(x) | all(sapply(x, is.null))

## Recursively step down into list, removing all such objects 
rmNullObs <- function(x) {
   x <- Filter(Negate(is.NullOb), x)
   lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x)
}

rmNullObs(lll)
# [[1]]
# [[1]][[1]]
# [1] 1
# 
# 
# [[2]]
# [[2]][[1]]
# [1] "a"
Run Code Online (Sandbox Code Playgroud)

以下是其应用于更深层嵌套列表的示例,其他当前提出的解决方案在其中各种失败.

LLLL <- list(lll)
rmNullObs(LLLL)
# [[1]]
# [[1]][[1]]
# [[1]][[1]][[1]]
# [[1]][[1]][[1]][[1]]
# [1] 1
# 
# 
# [[1]][[1]][[2]]
# [[1]][[1]][[2]][[1]]
# [1] "a"
Run Code Online (Sandbox Code Playgroud)


Dav*_*urg 21

这是一个使用FilterNegate组合的选项

Filter(Negate(function(x) is.null(unlist(x))), lll)
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
Run Code Online (Sandbox Code Playgroud)


Ric*_*ven 7

对于此特定示例,您还可以使用unlistrecursive参数.

lll[!sapply(unlist(lll, recursive=FALSE), is.null)]
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
Run Code Online (Sandbox Code Playgroud)


Len*_*rge 7

运用 purrr

purrr::map(lll, ~ purrr::compact(.)) %>% purrr::keep(~length(.) != 0)
[[1]]
[[1]][[1]]
[1] 1

[[1]][[2]]
[1] 2

[[1]][[3]]
[1] 3


[[2]]
[[2]][[1]]
[1] "a"

[[2]][[2]]
[1] "b"

[[2]][[3]]
[1] "c"
Run Code Online (Sandbox Code Playgroud)


the*_*ail 5

由于列表中有列表,因此您可能需要运行l/sapply两次,例如:

lll[!sapply(lll,sapply,is.null)]

#[[1]]
#[[1]][[1]]
#[1] 1
#
#
#[[2]]
#[[2]][[1]]
#[1] "a"
Run Code Online (Sandbox Code Playgroud)


小智 5

感谢Kun Ren使我们的生活更轻松,CRAN上有一个新的软件包列表

    list.clean(.data, fun = is.null, recursive = FALSE)
Run Code Online (Sandbox Code Playgroud)

或递归删除NULL:

    list.clean(.data, fun = is.null, recursive = TRUE)
Run Code Online (Sandbox Code Playgroud)