【发布时间】:2020-04-15 04:27:36
【问题描述】:
我正在尝试研究如何在 R 中定义自定义 for 循环,或者如果这可能的话。
示例
有几样东西会很高兴
- 相当于 ruby 的
each_with_index,以及 - 一个完全忽略异常的
for循环(无需manually code exception handling into the loop)。
是否可以在 R 中定义一种新的 for 循环(如果可以,如何定义),或者这是该语言的固有限制,因此无法做到?
用例
这是一个随机示例,说明 for_each_with_index 如何简化繁琐的算术
假设我们要从网站上抓取第 36 到第 55 篇文章,并将输出分配到列表中的某个位置。这很好用
library(rvest)
library(dplyr)
articles <- vector(mode = "list", length = 20)
for(i in 36:55) {
paste0("Scraping article ", i) %>% print
articles[[i - 35]] <- read_html(paste0("http://afr.herokuapp.com/articles/", i)) %>%
html_nodes("p") %>% html_text %>% paste0(collapse="/n")
}
但我们看到一些精细的算术(36:55、i - 35 等)理论上可以通过for_each_with_index 枚举articles 对象的每个元素来抽象出来,如下所示:
# NOT ACTUAL R CODE
library(rvest)
library(dplyr)
articles <- vector(mode = "list", length = 20)
for_each_with_index(articles, i) {
paste0("Scraping article ", i) %>% print
articles[[i]] <- read_html(paste0("http://afr.herokuapp.com/articles/", i + 35)) %>%
html_nodes("p") %>% html_text %>% paste0(collapse="/n")
}
通过使用for_each_with_index,我们避免了繁琐的算术。这个例子非常简单,但是当复杂度上升一些时,即当我们有各种条件、嵌套循环等时,事情会变得更加复杂,这些看似微小的清晰度改进会变得更加深刻
【问题讨论】:
-
@chinsoon12 我已经用一个例子更新了这个问题。对不起,它很长。我希望这是有道理的
-
见
lapply(36:55, function (i) {read_html(paste0(...))}) -
我看不出
i + 35比i - 35更不挑剔 -
本质区别不是 i + 35 和 i - 35 之间,而是使用 for 循环与不使用之间。 R 中的 for 循环效率非常低,涉及大量不必要的复制。它们在循环少量字符串时工作得很好,但是如果您必须对数十万条记录进行计算,for 循环会降低您的性能。
-
@BigFinger 是错误的:for 循环并不是特别低效。与其他控制构造(if、while 等)一样,它们是内部函数调用,只是在解析器中使用特殊规则来构造调用。如果您想要与 for 不同的语义,您可以定义自己的函数,但不能更改语言的语法,因此需要使用中缀运算符(如 Martin Morgan 的答案)或常规函数调用来完成。
标签: r