Dylan Russell
Dylan Russell

Reputation: 1098

R Fastest way to check if list is full of NULL

I have a function that under circumstances may output either a list of data.table's or a list of NULL. This list would like:

list(NULL, NULL, NULL)

The number of NULL's is subject to change.

What would be the fastest way to check that all elements of the list are NULL?

I so far have:

isNullList <- function(x) {
     all(sapply(x, is.null))
}

which works for:

x <- list(NULL, NULL, NULL)
isNullList(x)

y <- list("a", NULL, NULL)
isNullList(y)

Just wondering if there is a more efficient method?

UPDATE:

I have benchmarked my original attempt vs. the accepted answer below (isNullList2) by @RonakShah:

microbenchmark::microbenchmark(isNullList(x), isNullList2(x), times = 10000)
Unit: nanoseconds
           expr   min    lq     mean median    uq    max neval
  isNullList(x) 10100 10600 12172.54  11000 11500 370800 10000
 isNullList2(x)   700   800  1066.29    900  1100  29900 10000

Upvotes: 0

Views: 333

Answers (3)

hello_friend
hello_friend

Reputation: 5788

I think this may be fastest:

ul_bool_hf <- function(lst){is.null(unlist(lst))}

Upvotes: 0

Hugh
Hugh

Reputation: 16089

If the list can only be a list of NULLs or a list of data.tables, then you only need check the first element:

isNullList <- function(x) is.null(x[[1]])

Note that checking the lengths is not the same as checking NULL, even in your case:

library(data.table)
#> Warning: package 'data.table' was built under R version 4.0.2
yes <- list(NULL, NULL, NULL)
no1 <- list(data.table(), data.table(), data.table(), data.table())
no2 <- list(data.table(lapply(1:100, function(x) rep(x, 10))),
            data.table(lapply(1:200, function(x) rep(x, 10))),
            data.table(lapply(1:300, function(x) rep(x, 10))))

isNullList <- function(x) {
  all(sapply(x, is.null))
}

isNullList2 <- function(x) all(!lengths(x))

isNullList3 <- function(x) is.null(x[[1]])

isNullList(yes)
#> [1] TRUE
isNullList(no1)
#> [1] FALSE
isNullList(no2)
#> [1] FALSE

isNullList2(yes)
#> [1] TRUE
isNullList2(no1)
#> [1] TRUE
isNullList2(no2)
#> [1] FALSE

isNullList3(yes)
#> [1] TRUE
isNullList3(no1)
#> [1] FALSE
isNullList3(no2)
#> [1] FALSE

bench::mark(isNullList(yes), isNullList2(yes), isNullList3(yes))
#> # A tibble: 3 x 10
#>   expression         min        mean      median       max `itr/sec` mem_alloc
#>   <chr>         <bch:tm>    <bch:tm>    <bch:tm>  <bch:tm>     <dbl> <bch:byt>
#> 1 isNullLis~ 13200.000ns 16388.566ns 15800.000ns 165.100us    61018.    0.000B
#> 2 isNullLis~   900.000ns  1668.550ns  1100.000ns 141.900us   599323.    0.000B
#> 3 isNullLis~   300.000ns   468.580ns   300.000ns  21.900us  2134107.    0.000B
#> # ... with 3 more variables: n_gc <dbl>, n_itr <int>, total_time <bch:tm>
bench::mark(isNullList(no1), isNullList2(no1), isNullList3(no1))
#> Warning: Each result must equal the first result:
#>   `isNullList(no1)` does not equal `isNullList2(no1)`
#> # A tibble: 3 x 10
#>   expression         min        mean      median       max `itr/sec` mem_alloc
#>   <chr>         <bch:tm>    <bch:tm>    <bch:tm>  <bch:tm>     <dbl> <bch:byt>
#> 1 isNullLis~ 13000.000ns 16217.725ns 15800.000ns 157.100us    61661.    0.000B
#> 2 isNullLis~  3400.000ns  4088.379ns  3800.000ns 158.200us   244596.    0.000B
#> 3 isNullLis~   300.000ns   415.580ns   400.000ns 133.600us  2406276.    0.000B
#> # ... with 3 more variables: n_gc <dbl>, n_itr <int>, total_time <bch:tm>
bench::mark(isNullList(no2), isNullList2(no2), isNullList3(no2))
#> # A tibble: 3 x 10
#>   expression         min        mean      median       max `itr/sec` mem_alloc
#>   <chr>         <bch:tm>    <bch:tm>    <bch:tm>  <bch:tm>     <dbl> <bch:byt>
#> 1 isNullLis~ 12800.000ns 16139.422ns 15600.000ns 167.600us    61960.    0.000B
#> 2 isNullLis~  2800.000ns  3437.054ns  3200.000ns  21.600us   290947.    0.000B
#> 3 isNullLis~   200.000ns   395.230ns   300.000ns  17.600us  2530172.    0.000B
#> # ... with 3 more variables: n_gc <dbl>, n_itr <int>, total_time <bch:tm>

Created on 2020-09-18 by the reprex package (v0.3.0)

Upvotes: 1

Ronak Shah
Ronak Shah

Reputation: 388982

You could use lengths :

isNullList <- function(x) all(!lengths(x))

isNullList(x)
#[1] TRUE
isNullList(y)
#[1] FALSE

Upvotes: 2

Related Questions