我有两个长度相等的对象(一个是通过解析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 ++)?
答案 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)