假设我想运行一个循环,直到满足条件,此时保存结果并退出循环:
library(tidyverse)
for (i in 1:5) {
df <- iris %>% select(i) %>% head(2)
if (names(df) == "Petal.Width") {
out <- df
break
}
}
out
Run Code Online (Sandbox Code Playgroud)
如何在purr::map
不评估每个i的情况下重写它?
执行以下操作会得到我需要的结果,但必须评估5次,而for循环只需3次:
fun <- function(x) {
df <- iris %>% select(x) %>% head(2)
if (names(df) == "Petal.Width") {
return(df)
}
}
map_df(1:5, fun)
Run Code Online (Sandbox Code Playgroud)
没有等价物.实际上,使map
(和类似函数)在可读性方面优于一般循环的一件事是它们具有绝对可预测的行为:它们将为每个元素执行一次正确的函数,没有异常(除非,呃,如果有的话)例外:您可以通过stop
短路执行来提高条件,但这很少是可取的).
相反,你的情况并没有要求map
,它要求的东西沿着purrr::keep
或purrr::reduce
.
想想这样说:map
,reduce
,等都是对应于更一般的具体特例抽象for
循环.他们的目的是弄清楚正在处理哪种特殊情况.作为程序员,您的任务就是找到正确的抽象.
在您的特定情况下,我可能会使用dplyr完全重写语句,因此给出"最佳"的purrr解决方案很难:最好的解决方案是不使用purrr.也就是说,您可以使用purrr::detect
如下:
names(iris) %>%
detect(`==`, 'Sepal.Width') %>%
`[`(iris, .) %>%
head(2)
Run Code Online (Sandbox Code Playgroud)
要么
seq_along(iris) %>%
detect(~ names(iris[.x]) == 'Sepal.Width') %>%
`[`(iris, .) %>%
head(2)
Run Code Online (Sandbox Code Playgroud)
......但是真的,这里是比较的dplyr:
iris %>%
select(Sepal.Width) %>%
head(2)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
267 次 |
最近记录: |