Search (and return) the first element of the list that matches the (logical) test

As an example, I have a large list of vectors with different lengths (and some NULLs) and would like to find the first element of a list with two elements. As in this post, I know that with a list you can use a similar approach, using a sapply()subset of the first result. Since the solution in the above link using match()does not work in this case, I am curious if there is a more elegant (and more efficient from a calculation point of view) way of achieving this.

Reproducible example


# some example data
x <- list(NULL, NULL, NA, rep("foo", 6), c("we want", "this one"),
           c(letters[1:10]), c("foo", "bar"), NULL)
x

# find the first element of length 2 using sapply and sub-setting to result #1
x[sapply(x, FUN=function(i) {length(i)==2})][[1]]

Or, as in @Josh O'Brien, reply to this post ,

# get the index of the first element of length 2
seq_along(x)[sapply(x, FUN=function(i) {length(i)==2})]

Any thoughts or ideas?

+4
4

?

Find(function(i) length(i) == 2, x) # [1] "we want"  "this one"
Position(function(i) length(i) == 2, x) # [1] 5
+6

mapply

> x <- rep(x, 25000)
> microbenchmark({ x[match(2, mapply(length, x))] })
# Unit: milliseconds
#       min       lq   median       uq      max neval
#  243.7502 275.8941 326.2993 337.9221 405.7011   100

x[mapply(length, x) == 2][[1]]

sapply

>  x[sapply(x, length) == 2][[1]]
# [1] "we want"  "this one"

.

> x[ grep("2", summary(x)[,1])[1] ]
# [[1]]
# [1] "we want"  "this one"
+3

200 000 (28.8 ), rep(x, 25000). x , . :

> microbenchmark(Find(function(i) length(i) == 2, x),
                  x[sapply(x, length) == 2][[1]],
                  x[sapply(x, FUN=function(i) {length(i)==2})][[1]],
                  x[[match(2,lapply(x,length))]],
                  x[match(2, mapply(length, x))],
                  x[mapply(length, x) == 2][[1]])
Unit: microseconds
                                                        expr        min         lq      median          uq        max neval
                   Find(function(i) length(i) == 2, x)     89.104    107.531    112.8955    119.6605    466.045   100
                        x[sapply(x, length) == 2][[1]] 166539.621 185113.274 193224.0270 209923.2405 378499.180   100
x[sapply(x, FUN = function(i) {length(i) == 2 })][[1]] 279596.600 301976.512 310928.3845 322857.7610 484233.342   100
                      x[[match(2, lapply(x, length))]] 378391.882 388831.223 398639.1430 415137.0565 591727.647   100
                        x[match(2, mapply(length, x))] 207324.777 225027.221 235982.9895 249744.3525 422451.010   100
                        x[mapply(length, x) == 2][[1]] 205649.537 223045.252 236039.6710 249529.5245 411916.734   100

!

+3

match .

match(2,lapply(x,length))
#[1] 5
x[[match(2,lapply(x,length))]]
#[1] "we want"  "this one"
+1

All Articles