从列表列表中删除NULL元素

时间:2014-10-23 23:56:29

标签: r list null

如何从R:

中的列表列表中删除null元素,如下所示
lll <- list(list(NULL),list(1),list("a"))

我想要的对象看起来像:

lll <- list(list(1),list("a"))

我在这里看到了类似的答案:How can I remove an element from a list?但是无法将其从简单列表扩展到列表列表。

修改

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

lll <- list(list(NULL),list(1,2,3),list("a","b","c"))

如何获得:

lll <- list(list(1,2,3),list("a","b","c"))

7 个答案:

答案 0 :(得分:26)

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

它与Gabor Grothendieck对this quite similar question的回答密切相关。如果函数还要删除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"

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

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"

答案 1 :(得分:21)

以下是使用FilterNegate组合

的选项
Filter(Negate(function(x) is.null(unlist(x))), lll)
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"

答案 2 :(得分:7)

对于此特定示例,您还可以将unlist与其recursive参数一起使用。

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

答案 3 :(得分:6)

使用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"

答案 4 :(得分:5)

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

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

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

答案 5 :(得分:4)

CRAN上有一个新包 rlist ,感谢Kun Ren让我们的生活更轻松。

    list.clean(.data, fun = is.null, recursive = FALSE)

或递归删除NULL:

    list.clean(.data, fun = is.null, recursive = TRUE)

答案 6 :(得分:0)

快速解决Josh O&Brien的解决方案。功能列表存在一些问题

is.NullOb <- function(x) if(!(is.function(x))) is.null(x) | all(sapply(x, is.null)) else FALSE

## Recursively step down into list, removing all such objects 
rmNullObs <- function(x) {
  if(!(is.function(x))) {
    x = x[!(sapply(x, is.NullOb))]
    lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x)
  }
}