是不是可以在foreach中使用zip迭代器(即“拉链”两个迭代器)?

时间:2013-07-31 20:53:36

标签: r foreach iterator

我有两个长度相等的对象(一个是通过解析JSON生成的列表,另一个是一个多维数组的片段),例如:

library(rjson)
library(foreach)
iter1<-iter( fromJSON(file=jsonfilename)$someJSONarray )
iter2<-iter( myarr, by="row" )

我需要能够做到以下几点:

out=foreach(x=zipiter(iter1,iter2),combine=list) %do%
{
    #Do stuff with elements from both iterators accessed by e.g. x[[1]] and x[[2]]
}

有没有标准的方法(比如使用boost Zip迭代器的Python / C ++)?

3 个答案:

答案 0 :(得分:6)

izip包中有一个itertools函数可以执行您所描述的内容:

library(itertools)
out <- foreach(x=izip(iter1, iter2)) %do% {
    # x[[1]] contains a value from iter1
    # x[[2]] contains a value from iter2
}

但我更喜欢为foreach指定多个循环变量:

out <- foreach(x=iter1, y=iter2) %do% {
    # x contains a value from iter1
    # y contains a value from iter2
}

两个解决方案并行迭代迭代器中的值。如果你想要列表中的两个参数,那么izip会更方便。

答案 1 :(得分:1)

这可能不是您所需要的,但希望它至少可以让您走上正轨:

library(foreach)

X = 1:10
Y = 11:20

out = foreach(x=t(data.frame(X, Y))) %do% {x[1,]*x[2,]}

是的,这很奇怪,但它可以正确配对数据。如果你传入一个数据帧,foreach遍历列而不是行(这不是完全令人惊讶的,因为lapply执行相同的操作)。因此,对数据帧进行转置会导致对行进行迭代,但x对象是列向量,因此我们需要对行进行索引而不是像我们期望的那样对列进行索引。

答案 2 :(得分:0)

在史蒂夫韦斯顿的回答之后,没有什么可以补充的;我发布了自己的zip迭代器的工作版本,所以学习如何使用R中的迭代器的人们将受益。迭代器名为izipiter,以避免与现有izip迭代器发生名称冲突。

library(foreach)    
izipiter<- function(iters)
{
    nextEl<-function()
    {
        tryCatch(
        {
        foreach(it=iters,.combine=list) %do%
            nextElem(it)
        }, error=function(e) {stop("StopIteration")})
    }
    obj<-list(nextElem=nextEl)
    class(obj) <- c('izipiter','abstractiter','iter')
    obj
}

这是如何使用它:

it1=iter(c(3,5,15))
it2=iter(list(x="a",y="b",z=c("one","two","three")))

myit=izipiter(iters=list(it1,it2))

foreach(it=myit) %do%
    print(it)