zhy91
2021 年5 月 25 日 11:44
1
我需要先申明很多相同大小和类型的数组,目前的方法总感觉不够好,即:
const NX, NY, NZ = 64, 64, 64
a1 = Array{Float64}(undef, NX, NY, NZ)
a2 = Array{Float64}(undef, NX, NY, NZ)
a3 = Array{Float64}(undef, NX, NY, NZ)
# ...
Fortran 可以很方便直接定义:
real(8), dimension(NX,NY,NZ) :: a1, a2, a3 ! 还有很多。。。
通过搜索,发现了这个回答 :Declaring multiple arrays in Julia - Stack Overflow ,可是里面的两个答案也觉得不够优雅。第一种用表达式的方法还是太繁琐;第二种即下面的方法稍微好一点:
a1, a2, a3, a4, a5 = [Array{Float64}(undef, NX, NY, NZ) for i=1:5]
但是如果有非常多的数组,用 for
循环向量会不会先占用非常大的内存并耗费更多的时间?而且如果增加新的数组,还需要修改后面的总数,总感觉不够方便。
请问 Julia 中是否有更简单、更优雅的方式申明多个相同大小和类型的数组?就和 Fortran 的方法类似。谢谢!
using Base.Cartesian
const NX, NY, NZ = 64, 64, 64
@nexprs 3 i -> a_i = Array{Float64}(undef, NX, NY, NZ)
这样能产生a_1,a_2,a_3变量,如果变量是从1到10就把3改为10就可以。缺点是不能产生没有下划线的变量。
1 个赞
zhy91
2021 年5 月 25 日 14:00
4
非常感谢您的回答!
我其实想了解是否有比较通用的类似于 Fortran 的方法,这里 a1, a2, a3 其实只是示例,实际上的变量名之间没啥联系,比如是 ε0, ε, σ 之类的。
通过宏可以实现
例如ModelingToolkit.jl里的
@parameters x1, x2, x3
zhy91
2021 年5 月 26 日 01:54
6
非常感谢!
为了申明一些预分配大小的数组,专门引用一个包,是不是有点浪费了。。
不过我简单搜索了下,MATLAB 和 Python 好像也都没有什么比较方便的方式来一行申明多个数组,或许是解释型语言的代价?
如果想定义一些不一样的变量名,可以这样
a, b, c, x, y, z = @ntuple 6 i -> Array{Float64}(undef, NX, NY, NZ)
同样需要使用Base.Cartesian
自己写个宏就行了
macro muldef(def::Expr, vars::Symbol...)
defs = Expr(:block)
for var in vars
push!(defs.args, :($var=$def))
end
esc(defs)
end
#test
const NX, NY, NZ = 64, 64, 64
@muldef Array{Float64}(undef, NX, NY, NZ) a1 a2 a3
x, y, z, a, b, c = (Array{Float64}(undef, NX, NY, NZ) for _ in 1:6)
生成器不会占更多的内存
只是举个例子,你可以参考楼上的写法自己写个宏或者直接用list comprehension。
这个不能叫代价反而是优势吧,正因为是动态语言所以不用像C或Fortran一样做什么都要先声明。
struct Foo end
# only one allocation call is needed
as = Array{Foo}(undef, k, nx, ny, nz)
# why would one need this
for i = 1:k
@eval $(Symbol("a", i)) = view(as, $i, :, :, :)
end
1 个赞