Reputation: 1098
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
Reputation: 5788
I think this may be fastest:
ul_bool_hf <- function(lst){is.null(unlist(lst))}
Upvotes: 0
Reputation: 16089
If the list can only be a list of NULL
s or a list of data.table
s, 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
Reputation: 388982
You could use lengths
:
isNullList <- function(x) all(!lengths(x))
isNullList(x)
#[1] TRUE
isNullList(y)
#[1] FALSE
Upvotes: 2