在 Julia 中创建一个同时返回两个值的生成器

Eri*_*son 6 generator julia

给定一个生成器:

\n
myVec1 = rand(0:4, 2)\nmyVec2 = rand(0:4, 8)\n\nmyGen = (val1 + val2 for val1 in myVec1, val2 in myVec2)\n
Run Code Online (Sandbox Code Playgroud)\n

这基本上是一个有 2 列的矩阵。通过使用可以看出collect(myGen)

\n

如何创建一个每次调用生成两个值(基本上是一列)的生成器?

\n

从概念上讲,相当于:

\n
for myCol in eachcol(collect(myGen))\n    @show myCol;\nend\n
Run Code Online (Sandbox Code Playgroud)\n

只是没有对矩阵进行任何显式分配。

\n

我可以myGen针对以下情况进行包装吗:

\n
for value1, value2 in myGen\n  dosomethingelse1(value1, value2)\nend\n
Run Code Online (Sandbox Code Playgroud)\n

换句话说,我正在寻找一种方法来创建一个生成器,它一次返回 2 个(或更多?)连续值,并且可以在循环中使用它来执行此操作。

\n

所以基本上,我们在生成器中创建一个二维数组,我想立即访问整个切片。我可以使用实际数组来完成它eachcoleachrow但是生成器呢?

\n

这是一个测试用例:

\n
myVec1 = rand(0:4, 2);\nmyVec2 = rand(0:4, 800);\n\n@btime begin\n    myMat = [val1 + val2 for val1 in myVec1, val2 in myVec2];\n    outVec = [sum(myCol) for myCol in eachcol(myMat)];\nend\n\n@btime begin\n    myGen = (val1 + val2 for val1 in myVec1, val2 in myVec2);\n    outVec = [sum(myCol) for myCol in Iterators.partition(myGen, 2)];\nend\n
Run Code Online (Sandbox Code Playgroud)\n

@Bogumi\xc5\x82 Kami\xc5\x84ski 的解决方案确实有效,但在实践中,由于某种原因,它创建了更多的分配,而动机是减少它。

\n

ahn*_*abb 2

尽管其他答案在某些方面更通用,基于 OP 在其编辑中添加的信息,但更有效的内存选择是使用嵌套生成器。就像是:

\n
function solution_nested(v1, v2)\n    myGen = ((val1 + val2 for val1 in v1) for val2 in v2)\n    [sum(myCol) for myCol in myGen]\nend\n
Run Code Online (Sandbox Code Playgroud)\n

当您测试解决方案时,应避免使用全局变量,最好将解决方案包装在函数中,以便为 Julia 提供足够的机会来优化代码。

\n

该解决方案仅给出一次分配的预期结果:

\n
julia> @btime solution_nested(myVec1, myVec2);\n  1.856 \xce\xbcs (1 allocation: 6.38 KiB)\n
Run Code Online (Sandbox Code Playgroud)\n

因此,虽然这个解决方案不太符合标题,但它似乎符合您所描述的内容。我们使用惰性列的惰性序列。速度慢且内存效率低的原因Iterators.partition是它实际上分配了分区中值的中间向量: https: //github.com/JuliaLang/julia/blob/dacf9d65aff4668b8fff25957d9aaa2cf03868c8/base/iterators.jl#L1232

\n