5

我有两个长度相等的对象(一个是通过解析 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]]
}

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

4

3 回答 3

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更方便。

于 2013-08-01T17:28:38.627 回答
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对象是列向量,所以我们需要索引行而不是我们期望的列。

于 2013-07-31T21:22:51.973 回答
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)
于 2013-08-01T17:38:11.867 回答