我假设您想遍历 spamdata 的元素并建立一个指示符,是否在您的电子邮件主题行中找到字符串 "viagra"。
让我们设置一些虚拟数据用于说明目的:
subjects <- c("Buy my viagra", "Buy my Sildenafil citrate",
"UK Lottery Win!!!!!")
names(subjects) <- rep("Subject", 3)
spamdata <- list(list(Header = subjects[1]), list(Header = subjects[2]),
list(Header = subjects[3]))
接下来我们创建一个向量words 来保存循环每次迭代的结果。您不想在每次迭代中增长words 或任何其他对象 - 这将强制复制并减慢您的循环速度。而是在开始之前分配存储空间 - 这里使用我们要循环的列表的长度:
words <- logical(length = length(spamdata))
你可以这样设置循环
## seq_along() creates a sequence of 1:length(spamdata)
for(i in seq_along(spamdata)) {
words[ i ] <- grepl("viagra", spamdata[[ i ]]$Header["Subject"])
}
然后我们可以查看words:
> words
[1] TRUE FALSE FALSE
这与我们从虚构的主题中所知道的相符。
注意我们如何使用i 作为1、2 和3 的占位符 - 在循环的每次迭代中,i 采用序列1 中的下一个值, 2,3 所以我们可以 i) 访问 spamdata 的 ith 组件以获取下一个主题行,和 ii) 访问 @987654341 的 ith 元素@ 存储grepl() 调用的结果。
请注意,我们还可以使用sapply() 或lapply() 函数代替隐式循环,它们会为您创建循环,但可能需要一些工作来编写自定义函数。我们可以写一个包装器,而不是直接使用grepl():
foo <- function(x) {
grepl("viagra", x$Header["Subject"])
}
在上述函数中,我们使用x 而不是列表名称spamdata,因为当lapply() 和sapply() 循环遍历spamdata 列表时,各个组件(在@987654353 中由spamdata[[i]] 引用@loop) 作为参数x 传递给我们的函数,因此我们只需要在grepl() 调用中引用x。
这就是我们如何在lapply() 或sapply() 中使用我们的包装函数foo(),首先是lapply():
> lapply(spamdata, foo)
[[1]]
[1] TRUE
[[2]]
[1] FALSE
[[3]]
[1] FALSE
sapply() 将尽可能简化返回的对象,如下所示:
> sapply(spamdata, foo)
[1] TRUE FALSE FALSE
除此之外,它们的工作方式类似。
请注意,我们可以让我们的包装函数 foo() 更有用,方法是允许它接受一个参数来定义您希望搜索的垃圾邮件词:
foo <- function(x, string) {
grepl(string, x$Header["Subject"])
}
我们可以像这样使用lapply() 和sapply() 向我们的函数传递额外的参数:
> sapply(spamdata, foo, string = "viagra")
[1] TRUE FALSE FALSE
> sapply(spamdata, foo, string = "Lottery")
[1] FALSE FALSE TRUE
您会发现哪个最有用(for() 循环或lapply()、sapply() 版本)取决于您的编程背景以及您最熟悉的。有时for() 使用起来更容易和简单,但可能更冗长(这并不总是一件坏事!),而lapply() 和sapply() 在您不需要跳过箍的地方非常简洁和有用创建一个可行的包装函数。