我需要对可变数量的数组有效地实现笛卡尔积。
我已经尝试过product
from 的功能Iterators.jl
,但性能欠佳。
我是一名 python 黑客,使用了 sklearn 的这个功能,并获得了良好的性能结果。
我曾尝试编写此函数的 Julia 版本,但无法产生与 python 函数相同的结果。
我的代码是:
function my_repeat(a, n)
# mimics numpy.repeat
m = size(a, 1)
out = Array(eltype(a), n * m)
out[1:n] = a[1]
for i=2:m
out[(i-1)*n+1:i*n] = a[i]
end
return out
end
function cartesian(arrs; out=None)
dtype = eltype(arrs[1])
n = prod([size(i, 1) for i in arrs])
if is(out, None)
out = Array(dtype, n, length(arrs))
end
m = int(n / size(arrs[1], 1))
out[:, 1] = my_repeat(arrs[1], m)
if length(arrs[2:]) > 0
cartesian(arrs[2:], out=out[1:m, 2:])
for j = 1:size(arrs[1], 1)-1
out[(j*m + 1):(j+1)*m, 2:] = out[1:m, 2:]
end
end
return out
end
我用以下方法测试它:
aa = ([1, 2, 3], [4, 5], [6, 7])
cartesian(aa)
返回值为:
12x3 Array{Float64,2}:
1.0 9.88131e-324 2.13149e-314
1.0 2.76235e-318 2.13149e-314
1.0 9.88131e-324 2.13676e-314
1.0 9.88131e-324 2.13676e-314
2.0 9.88131e-324 2.13149e-314
2.0 2.76235e-318 2.13149e-314
2.0 9.88131e-324 2.13676e-314
2.0 9.88131e-324 2.13676e-314
3.0 9.88131e-324 2.13149e-314
3.0 2.76235e-318 2.13149e-314
3.0 9.88131e-324 2.13676e-314
3.0 9.88131e-324 2.13676e-314
我相信这里的问题是当我使用这一行时:cartesian(arrs[2:], out=out[1:m, 2:])
关键字参数out
没有在递归调用中就地更新。
可以看出,我对这个函数的 Python 版本做了一个非常天真的翻译(见上面的链接)。很可能存在内部语言差异,使天真的翻译变得不可能。我不认为这是真的,因为来自 julia 文档的函数部分的引用:
Julia 函数参数遵循有时称为“传递共享”的约定,这意味着值在传递给函数时不会被复制。函数参数本身充当新的变量绑定(可以引用值的新位置),但它们引用的值与传递的值相同。在函数内对可变值(例如数组)所做的修改将对调用者可见。这与 Scheme、大多数 Lisps、Python、Ruby 和 Perl 以及其他动态语言中的行为相同。
我怎样才能使这个(或等效的)函数在 Julia 中工作?