如何在 Julia 中检索数组的数组?

How do I retrieve an array of arrays of arrays in Julia?

我是 Julia 新人,所以请不要评判我(哈哈)

这是我的情况:我需要保存几个 2x2x2 矩阵,其元素是 4 个元素的向量,但现在当我尝试从文件中检索它们时,我不能!!!

这是我做的:

为了创建这些矩阵,我创建了这个函数

function InitialConf(L_=2,S_=2,T_=2,Dim_=4)
  Conf_=Array{Array{Float64,1}}(L_,S_,T_)
  for i_ = 1:L_, j_=1:S_,k_=1:T_
    Conf_[i_,j_,k_]=RanUniVec(Dim_)
  end
  return Conf_ 
end

其中 RanUniVec(Dim_) 是创建这些具有特殊特征的 4 维向量的函数,这些特征对于本次讨论并不重要:

function RanUniVec(Dim_)
  vector_=Array{Float64}(Dim_)
  while true
    for i_ in 1:Dim_
      vector_[i_]=UniformRand(-1,1)
    end
    if norm(vector_)<1 && norm(vector_)>0.5
      break
    end
  end
  vector_=normalize(vector_) # 2-norm
  return vector_ 
end


function UniformRand(a_,b_)
  rand_=(b_-a_)*rand()+a_
  return rand_
end

我需要其中两个矩阵(例如)所以我做了下一个:

States=[]
Conf1=InitialConf()
Conf2=InitialConf()
push!(States,Conf1)
push!(States,Conf2)

f=open("Info.txt","w") do f
    write(f,"$States")
end

这使得我的信息所在的 Info.txt 文件,但是当我再次尝试从中获取 States 数组时这个文件,Julia 告诉我它不能

f=readlines("Info.txt")
States=parse(f)

ERROR: MethodError: no method matching parse(::Array{String,1})
Closest candidates are:
  parse(::Type{IPv4}, ::AbstractString) at socket.jl:167
  parse(::Type{IPv6}, ::AbstractString) at socket.jl:218
  parse(::Type{DateTime}, ::AbstractString, ::DateFormat{Symbol("yyyy-mm-dd\THH:MM:SS.s"),Tuple{Base.Dates.DatePart{'y'},Base.Dates.Delim{Char,1},Base.Dates.DatePart{'m'},Base.Dates.Delim{Char,1},Base.Dates.DatePart{'d'},Base.Dates.Delim{Char,1},Base.Dates.DatePart{'H'},Base.Dates.Delim{Char,1},Base.Dates.DatePart{'M'},Base.Dates.Delim{Char,1},Base.Dates.DatePart{'S'},Base.Dates.Delim{Char,1},Base.Dates.DatePart{'s'}}}) at dates/parse.jl:202

...

你知道我怎样才能再次获得我的 State 数组吗?

一般来说,您应该使用长 运行 评论中 Colin 的推荐。如果您确实已经生成了这些文本文件,那么您可以执行以下操作。我将使用一个较小的示例。

假设您的原始数组由两个 2x2x2 数组组成。这是我将使用的示例:

julia> z
2-element Array{Array{Int64,3},1}:
 [1 2; 3 4]

[10 20; 30 40]
 [1 2; 3 4]

[10 20; 30 40]

julia> z[1]
2×2×2 Array{Int64,3}:
[:, :, 1] =
 1  2
 3  4

[:, :, 2] =
 10  20
 30  40

julia> z[2]
2×2×2 Array{Int64,3}:
[:, :, 1] =
 1  2
 3  4

[:, :, 2] =
 10  20
 30  40

现在它将作为以下字符串保存到文件中:

julia> repr(z)
"Array{Int64,3}[[1 2; 3 4]\n\n[10 20; 30 40], [1 2; 3 4]\n\n[10 20; 30 40]]"

并且解析这个字符串显然会失败。您需要做的是编辑您的文件,以在大数组的每个条目上添加 cat 方法调用,并将维度 3 作为您要对其进行分类的维度。

这意味着从保存文件的原始内容:

Array{Int64,3}[[1 2; 3 4]

[10 20; 30 40], [1 2; 3 4]

[10 20; 30 40]]

你必须让这个文件包含:

Array{Int64,3}[cat(3, [1 2; 3 4], [10 20; 30 40]),
               cat(3, [1 2; 3 4], [10 20; 30 40])]

这些更改可以手动完成,也可以编写程序来执行转换(您必须将 , 替换为 ), cat(3,\n\n 替换为 ,; 确保添加第一个 cat 和最后一个 ),因为它们不会被前两个规则捕获)。

现在,如果您将它作为字符串读取,您可以评估解析它的结果:

julia> s = """Array{Int64,3}[cat(3, [1 2; 3 4], [10 20; 30 40]),
                          cat(3, [1 2; 3 4], [10 20; 30 40])]"""
"Array{Int64,3}[cat(3, [1 2; 3 4], [10 20; 30 40]),\ncat(3, [1 2; 3 4], [10 20; 30 40])]"

julia> eval(parse(s))[2]
2×2×2 Array{Int64,3}:
[:, :, 1] =
 1  2
 3  4

[:, :, 2] =
 10  20
 30  40

但是请注意,不推荐所有这些 - 最好使用 Colin 推荐的包来执行此操作。

不是直接回答你的具体问题,而是对未来发展的一般性建议。要将数据保存到磁盘并稍后重新加载,请优先使用 JLD2.jl.

等格式

您使用

保存
@save "filename.jld2" ARRAY

并加载

@load "filename.jld2" ARRAY

无需弄清楚您过去选择的格式是什么。避免复杂数据结构的麻烦。