Remove NULL elements from list of lists

后端 未结 7 1959
天涯浪人
天涯浪人 2020-11-27 20:20

How do I remove the null elements from a list of lists, like below, in R:

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

The object I want

相关标签:
7条回答
  • 2020-11-27 20:27

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

    lll[!sapply(lll,sapply,is.null)]
    
    #[[1]]
    #[[1]][[1]]
    #[1] 1
    #
    #
    #[[2]]
    #[[2]][[1]]
    #[1] "a"
    
    0 讨论(0)
  • 2020-11-27 20:27

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

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

    or for recursive removal of NULL:

        list.clean(.data, fun = is.null, recursive = TRUE)
    
    0 讨论(0)
  • 2020-11-27 20:32

    For this particular example you can also use unlist with its recursive argument.

    lll[!sapply(unlist(lll, recursive=FALSE), is.null)]
    # [[1]]
    # [[1]][[1]]
    # [1] 1
    #
    #
    # [[2]]
    # [[2]][[1]]
    # [1] "a"
    
    0 讨论(0)
  • 2020-11-27 20:33

    Here's an option using Filter and Negate combination

    Filter(Negate(function(x) is.null(unlist(x))), lll)
    # [[1]]
    # [[1]][[1]]
    # [1] 1
    #
    #
    # [[2]]
    # [[2]][[1]]
    # [1] "a"
    
    0 讨论(0)
  • 2020-11-27 20:41

    Quick fix on Josh O'Brien's solution. 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)
      }
    }
    
    0 讨论(0)
  • 2020-11-27 20:44

    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.

    ## 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"
    
    0 讨论(0)
提交回复
热议问题