list 从列表列表中删除 NULL 元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26539441/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 08:05:42  来源:igfitidea点击:

Remove NULL elements from list of lists

rlistnull

提问by Chris

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?but was not able to extend it from simple lists to a list of lists.

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

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"))

回答by Josh O'Brien

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. 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.

它与 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"

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"

回答by David Arenburg

Here's an option using Filterand Negatecombination

这是使用FilterNegate组合的选项

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

回答by Leni Ohnesorge

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"

回答by Rich Scriven

For this particular example you can also use unlistwith its recursiveargument.

对于这个特定示例,您还可以使用unlist它的recursive参数。

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

回答by thelatemail

Since you have lists in lists, you probably need to run l/sapplytwice, like:

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

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

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

回答by Raminsu

There is a new package rliston CRAN, thanks to Kun Ren for making our life easier.

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

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

or for recursive removal of NULL:

或递归删除NULL:

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

回答by bramtayl

Quick fix on Josh O'Brien's solution. There's a bit of an issue with lists of functions

快速修复 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)
  }
}