在Julia中生成直线网格坐标
在Julia中,制作这样的(X,Y)数组的最佳方法是什么在Julia中生成直线网格坐标,julia,Julia,在Julia中,制作这样的(X,Y)数组的最佳方法是什么 0 0 1 0 2 0 3 0 0 1 1 1 2 1 3 1 0 2 1 2 2 2 3 2 0 3 1 3 2 3 3 3 坐标是规则的和直线的,但不一定是整数。这似乎可以做到这一点。不过,我不确定这是最好的解决方案。看起来有点复杂 xs = 0:3; ys = 0:3; out = [[xs[i] for i in 1:length(xs), j in 1:length(ys)][:] [ys[j] for i in 1:leng
0 0
1 0
2 0
3 0
0 1
1 1
2 1
3 1
0 2
1 2
2 2
3 2
0 3
1 3
2 3
3 3
坐标是规则的和直线的,但不一定是整数。这似乎可以做到这一点。不过,我不确定这是最好的解决方案。看起来有点复杂
xs = 0:3;
ys = 0:3;
out = [[xs[i] for i in 1:length(xs), j in 1:length(ys)][:] [ys[j] for i in 1:length(xs), j in 1:length(ys)][:]]
听起来像是一份工作:
hcat(重复(0:3,外部=4),重复(0:3,内部=4))
注意,当
xs
或ys
较小时(例如3
,30
),它比数组理解慢得多 Julia 0.6包括一个高效的产品
迭代器,它允许第四种解决方案。比较所有解决方案:
using Base.Iterators
f1(xs, ys) = [[xs[i] for i in 1:length(xs), j in 1:length(ys)][:] [ys[j] for i in 1:length(xs), j in 1:length(ys)][:]]
f2(xs, ys) = hcat(repeat(xs, outer=length(ys)), repeat(ys, inner=length(xs)))
f3(xs, ys) = vcat(([x y] for y in ys for x in xs)...)
f4(xs, ys) = (eltype(xs) == eltype(ys) || error("eltypes must match");
reinterpret(eltype(xs), collect(product(xs, ys)), (2, length(xs)*length(ys)))')
xs = 1:3
ys = 0:4
@show f1(xs, ys) == f2(xs, ys) == f3(xs, ys) == f4(xs, ys)
using BenchmarkTools
@btime f1($xs, $ys)
@btime f2($xs, $ys)
@btime f3($xs, $ys)
@btime f4($xs, $ys)
在我的电脑上,这会导致:
f1(xs, ys) == f2(xs, ys) == f3(xs, ys) == f4(xs, ys) = true
548.508 ns (8 allocations: 1.23 KiB)
3.792 μs (49 allocations: 2.45 KiB)
1.916 μs (51 allocations: 3.17 KiB)
353.880 ns (8 allocations: 912 bytes)
对于xs=1:300
和ys=0:400
我得到:
f1(xs, ys) == f2(xs, ys) == f3(xs, ys) == f4(xs, ys) = true
1.538 ms (13 allocations: 5.51 MiB)
1.032 ms (1636 allocations: 3.72 MiB)
16.668 ms (360924 allocations: 24.95 MiB)
927.001 μs (10 allocations: 3.67 MiB)
编辑:
到目前为止,最快的方法是在预分配阵列上直接循环:
function f5(xs, ys)
lx, ly = length(xs), length(ys)
res = Array{Base.promote_eltype(xs, ys), 2}(lx*ly, 2)
ind = 1
for y in ys, x in xs
res[ind, 1] = x
res[ind, 2] = y
ind += 1
end
res
end
对于xs=1:3
和ys=0:4
,f5
需要65.339纳秒(1个分配:336字节)
对于xs=1:300
和ys=0:400
,需要280.852μs(2次分配:1.84 MiB)
编辑2:
包括Dan Getz评论中的f6
:
function f6(xs, ys)
lx, ly = length(xs), length(ys)
lxly = lx*ly
res = Array{Base.promote_eltype(xs, ys), 2}(lxly, 2)
ind = 1
while ind<=lxly
@inbounds for x in xs
res[ind] = x
ind += 1
end
end
for y in ys
@inbounds for i=1:lx
res[ind] = y
ind += 1
end
end
res
end
功能f6(xs,ys)
lx,ly=长度(xs),长度(ys)
lxly=lx*ly
res=数组{Base.promote_eltype(xs,ys),2}(lxly,2)
ind=1
而INDI
vcat(([xy]表示0:3中的x表示0:3中的y)
您需要什么?啊,是的,这非常简洁,非常有效,谢谢!难道你不想用一个惰性数组来代替数字数组吗?在这里使用实际数组似乎是MATLAB/R/Python的坏习惯。通常这些数字是任意输入的。碰巧我的任意输入之一是一个网格。因此,在我的例子中,通常不能将其作为惰性数组编写。另外,实际上数组只有2x200,所以我并不真正关心几个字节。我只是发现——也许它们很有用。从f5
中再压缩一点,