【问题标题】:Is it possible to have zip iterator (i.e. "zip" two iterators together) in foreach?是否可以在 foreach 中使用 zip 迭代器(即“压缩”两个迭代器)?
【发布时间】:2013-08-01 14:13:01
【问题描述】:

我有两个长度相等的对象(一个是解析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 迭代器)?

【问题讨论】:

    标签: r foreach iterator


    【解决方案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 对象是列向量,因此我们需要索引行而不是我们期望的列。

    【讨论】:

    • 谢谢。它当然可以解决问题。这不是很简单,也不是记录在案的技巧,是吗?
    • 很高兴我能帮上忙。您可能还想尝试使用其他数据结构(例如矩阵)来尝试使用此策略,以防将数据转换为 df 会减慢操作速度。如您所见,我仅在 10 对记录上进行了尝试,但我假设您可能拥有更多数据,因为您使用的是 foreach 和迭代器。
    【解决方案2】:

    itertools 包中有一个 izip 函数,可以满足您的描述:

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

    【讨论】:

    • 太棒了!我以为它是关于迭代压缩(压缩)文件...我刚刚制作了自己的 izip 迭代器,甚至将其命名为izipiter 以避免与izip 的名称冲突...我现在觉得很傻。至少我学到了一些关于迭代器构造的东西。谢谢!
    • @AdamRyczkowski 我以 Python itertools 包中的 izip 函数命名它。事实上,许多迭代器和 foreach 包都是从 Python 复制而来的。例如,foreach 尝试复制 Python 列表推导式。
    【解决方案3】:

    在史蒂夫韦斯顿的回答之后,没有什么可补充的;我会发布我自己的 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-22
      • 1970-01-01
      • 1970-01-01
      • 2013-09-12
      • 2020-01-05
      • 2011-05-07
      • 1970-01-01
      • 2019-12-03
      相关资源
      最近更新 更多