[英]Remove NULL elements from list of lists
How do I remove the null elements from a list of lists, like below, in R:如何从列表列表中删除空元素,如下所示,在 R 中:
lll <- list(list(NULL),list(1),list("a"))
The object I want would look like:我想要的对象看起来像:
lll <- list(list(1),list("a"))
I saw a similar answer here: How can I remove an element from a list?我在这里看到了类似的答案: How can I remove an element from a list? but was not able to extend it from simple lists to a list of lists.但无法将其从简单列表扩展到列表列表。
EDIT编辑
Bad example above on my part.我上面的坏例子。 Both answers work on simpler case (above).两个答案都适用于更简单的情况(上图)。 What if list is like:如果列表是这样的怎么办:
lll <- list(list(NULL),list(1,2,3),list("a","b","c"))
How to get:怎么获得:
lll <- list(list(1,2,3),list("a","b","c"))
This recursive solution has the virtue of working on even more deeply nested lists.这种递归解决方案的优点是可以处理更深的嵌套列表。
It's closely modeled on Gabor Grothendieck's answer to this quite similar question .它与 Gabor Grothendieck 对这个非常相似的问题的回答密切相关。 My modification of that code is needed if the function is to also remove objects like list(NULL)
(not the same as NULL
), as you are wanting.如果该函数还根据需要删除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"
Here is an example of its application to a more deeply nested list, on which the other currently proposed solutions variously fail.这是将其应用于更深层嵌套列表的示例,在该列表上其他当前提出的解决方案各不相同。
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"
Here's an option using Filter
and Negate
combination这是一个使用Filter
和Negate
组合的选项
Filter(Negate(function(x) is.null(unlist(x))), lll)
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
Using purrr
使用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"
For this particular example you can also use unlist
with its recursive
argument.对于此特定示例,您还可以将unlist
与其recursive
参数一起使用。
lll[!sapply(unlist(lll, recursive=FALSE), is.null)]
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
Since you have lists in lists, you probably need to run l/sapply
twice, like:由于列表中有列表,您可能需要运行l/sapply
两次,例如:
lll[!sapply(lll,sapply,is.null)]
#[[1]]
#[[1]][[1]]
#[1] 1
#
#
#[[2]]
#[[2]][[1]]
#[1] "a"
Quick fix on Josh O'Brien's solution.快速修复 Josh O'Brien 的解决方案。 There's a bit of an issue with lists of functions函数列表有点问题
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)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.