如何从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"))
答案 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)
以下是使用Filter
和Negate
组合
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)
}
}