Julia中两个向量的笛卡尔积

13

我有两个向量xy,长度分别为n和p。是否有一种内置的方法可以创建一个np x 2矩阵,它将是

x[1] y[1]
x[1] y[2]
...
x[1] y[p]
x[2] y[1]
...
x[n] y[p]

我可以用嵌套的for循环来实现,但我在寻找一个内置函数(如果存在的话)。


有人知道如何修改答案,如果我想要一个n乘p的有序对矩阵,其中第i行第j列是(x[i], y[j])。 - seeker_after_truth
4个回答

18

至少在Julia 1.3中,有一个内置函数Iterators.product,所以Iterators.product(a, b) |> collect就能达到目的。


5
请注意,Iterators 是 Julia 的 Base 模块的一部分(Base.Iterators),因此您无需调用 importusing 就可以使用 Iterators.product - JoseOrtiz3

12

这是在IterTools模块中提供的(该模块取代了Iterators模块)。

摘自https://github.com/JuliaCollections/IterTools.jl

迭代输入的笛卡尔积中的所有组合。

示例:

using IterTools
for p in product(1:3,1:2)
    @show p
end

p = (1,1)
p = (2,1)
p = (3,1)
p = (1,2)
p = (2,2)
p = (3,2)

1
我不确定它是否替代了Iterators模块,因为在使用Julia 1.3rc4中的Itertools.product时,它说已被弃用,推荐使用Iterators.product。 - Matěj Račinský
这个解决方案在我使用 Julia 1.5 时运行速度更快。 - Nacho

10

如果Julia在嵌套循环中通常很快,所以如果它们对您而言正常工作,您应该检查性能,或者只需坚持使用它。

另一个选择是使用repmat(这比使用repeat稍快):

[repmat(x,1,length(y))'[:] repmat(y,length(x),1)[:]]

我快速测试了这两种方法:

x=rand(1000)
y=rand(1000)

function withrepeat(x,y)
    [repeat(x, inner=[size(y,1)]) repeat(y, outer=[size(x,1)])]
end

function withrepmat(x,y)
    [repmat(x,1,length(y))'[:] repmat(y,length(x),1)[:]]
end

withrepeat(x,y)
elapsed time: 0.21556302 seconds (95986112 bytes allocated)

with repmat(x,y)
elapsed time: 0.075604488 seconds (56000560 bytes allocated)

不确定为什么差别这么大,我认为还有改进的空间。 还没有尝试Iterators.jl包中的产品功能。

此外,在这里提供了更多的信息:https://groups.google.com/forum/#!topic/julia-users/dtl--SyFgwY

希望这可以帮到您。

尝试了几个嵌套循环,确实更快:

function withloops (x,y)
    leny=length(y)
    lenx=length(x)
    m=leny*lenx
    OUT = zeros(Float64, m,2)
    c=1
    for i = 1:lenx
        for j = 1:leny
            OUT[c,1] = x[i]
            OUT[c,2] = y[j]
            c+=1
        end
    end 
    return OUT
end

对于相同的rand(1000),应用于xy

withloops(x,y)
elapsed time: 0.011350679 seconds (16000128 bytes allocated)

1
@inboundsfor 循环有帮助吗? - rickhg12hs
1
@rickhg12hs 应该是的,我发布时有点匆忙,没有时间进行充分的测试,但我会在明天进行测试并相应地编辑帖子。感谢您的建议。 - epx
我尝试使用@inbounds,但没有任何明显的改进,也许这是因为数组中没有任何操作,我只是在赋值?此外,在我的计算机上,使用长度为10000的向量作为“x”和“y”的输入时,使用“repeat”或“repmat”会产生内存错误,但使用嵌套循环函数却可以正常工作。 - epx

6

以下是我可能会的方法:

julia> x = [1, 2, 3, 4];

julia> y = [9, 8, 7];

julia> [repeat(x, inner=[size(y,1)]) repeat(y, outer=[size(x,1)])]
12x2 Array{Int64,2}:
 1  9
 1  8
 1  7
 2  9
 2  8
 2  7
 3  9
 3  8
 3  7
 4  9
 4  8
 4  7

您可能还想看一下Iterators.jl——特别是product函数。


请注意,您可以省略innerouter参数周围的括号,因此公式简化为[repeat(x, inner=size(y,1)) repeat(y, outer=size(x,1))] - Robert Hönig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接