R语言中的循环及其扩展:iter和foreach

R中有三种不同的循环结构:

1.repeat结构

它只是简单的重复同一个表达式:repeat expression,如果要跳出循环,可以使用break命令,若要跳至循环中的下一轮迭代,需要使用next命令;如果在循环中不包括break命令,R代码将会是一个无限循环。

因此,常用的结构如下:

repeat { 
   expression
   if(condition){
        break
   }
}

举例如下:

# 求1-100的和
i <- 1
sum_100 <- 0
repeat{sum_100 = sum_100 + i
       i=i+1
       if(i>100){
         print(sum_100)
         break
       }
}

2.while结构:在某个条件为真时,重复某一特定的表达式

while(condition) expression

举例如下:

> i <- 1
> sum_100 <- 0
> while(i<=100){sum_100=sum_100+i;i=i+1}
> print(sum_100)
[1] 5050

3. for循环结构可以遍历向量或者列表中的每个元素:

for(var in list) expression

举例如下:

> for(i in seq(from=1,to=100,by=1)) sum_100=sum_100+i
> sum_100
[1] 5050

 4.循环扩展

我们都知道C#或者java等现代编程语言中,都会有foreach等迭代器。R语言本身并没有提供这样的机制,不过我们可以通过R语言添加包来实现

(1)迭代器:从另外一个对象中返回元素的抽象对象。使用迭代器可以使代码具有更好的可读性同时易于并行执行。添加R语言扩展包iterators可以实现迭代器功能。迭代器可以返回向量、数组、数据框或者其他对象的元素,当然也可以返回函数。

iter(obj,checkFunc=function(...) TRUE,recycle=FALSE,...)
# obj 指定对象
# checkFunc 指定一个过滤迭代器返回值的函数
# recyle 指定当对象元素迭代完成之后是否对迭代进行重置

举例如下:

> iter_one <- iter(1:10,checkFunc=function(x) x%%2==0,recycle=F)
> nextElem(iter_one)   #nextElem()函数用来查看下一个迭代项,这个函数会隐式地调用checkFunc,如果下一个值符合checkFunc,则返回该值,否则将迭代下一个值,直至找到一个符合checkFunc的值或者将所有值都迭代完毕
[1] 2
> nextElem(iter_one)
[1] 4
> nextElem(iter_one)
[1] 6
> nextElem(iter_one)
[1] 8
> nextElem(iter_one)
[1] 10
> nextElem(iter_one)
Error: StopIteration   #由于设定了recycle=F(也是默认值),迭代完成后,再次调用nextElem()函数将会出现Error:StopIteration.如果设置recycle=T,此时迭代将重置,再次输出2,4,6,8,10

(2)foreach循环:该功能通过R语言扩展包foreach实现,foreach能够循环遍历某个对象(向量、矩阵、数据框或者迭代器)中的多个元素,针对各个元素执行表达式,并返回结果。

foreach(..., .combine, .init, .final=NULL, .inorder=TRUE,
       .multicombine=FALSE,
       .maxcombine=if (.multicombine) 100 else 2,
       .errorhandling=c('stop', 'remove', 'pass'),
       .packages=NULL, .export=NULL, .noexport=NULL,
       .verbose=FALSE)

真正执行foreach循环,需要使用%do%或者%dopar%运算符

> i_square <- foreach(i=1:5) %do% i^2
> i_square
[[1]]
[1] 1

[[2]]
[1] 4

[[3]]
[1] 9

[[4]]
[1] 16

[[5]]
[1] 25

%do%运算符顺序执行表达式,而%dopar%运算符可以用来并行执行表达式。