Equivalent of `break` in purrr::map

• A+
Category：Languages

Say I want to run a loop until a condition is met, at which point the result is saved and the loop exits:

``library(tidyverse)  for (i in 1:5) {    df <- iris %>% select(i) %>% head(2)    if (names(df) == "Petal.Width") {     out <- df     break     } }  out ``

How can I rewrite this using `purr::map` without having to evaluate each i?

Doing the following gives the result I need, but has to evaluate 5 times, whereas the for loop only 3 times:

``fun <- function(x) {    df <- iris %>% select(x) %>% head(2)    if (names(df) == "Petal.Width") {   return(df)   } }  map_df(1:5, fun) ``

1) `callCC` can be used to get this effect:

``callCC(function(k) {   fun2 <- function(x) {     print(x) # just to show that x = 5 is never run     df <- iris %>% select(x) %>% head(2)     if (names(df) == "Petal.Width") k(df)   }   map_df(1:5, fun2) }) ``

giving:

``[1] 1 [1] 2 [1] 3 [1] 4   Petal.Width 1         0.2 2         0.2 ``

1a) If it is important to use `fun` without change then try this instead:

``callCC(function(k) map_df(1:5, ~ if (!is.null(df <- fun(.x))) k(df))) ``

2) purrr::reduce An alternative is to use `reduce` from purrr (or `Reduce` from base R):

``f <- function(x, y) if (is.null(x)) fun(y) else x reduce(1:5, f, .init = NULL) ``

This is not as good as (1) and (1a) from the viewpoint that it will still involve iterating over each element of 1:5 but will only invoke `fun` for 1:4. In contrast (1) and (1a) actually return after running `fun` or `fun2` on 4.