如何在 Julia 中声明行长度不同的二维数组?

How to declare a 2d array whose rows vary in length in Julia?

我想声明一个呈锯齿形的二维数组,如下所示:

***
************
******
*
*
**

其中每个星号表示一个整数。这意味着其行的长度从上到下不同。向量的向量似乎适合这种情况,我的代码是:


struct In
  cols :: Vector{Int};
end 

struct Out
  nlen :: Int;
  rows :: Vector{In};
  function Out(n)  
    o = new(n, Vector{In}(undef,n));
    
    for i in 1:n
      o.rows(i).cols = Vector{Int}(undef,i);
    end
    

    return o

  end
end


myarray = Out(5);

运行 上面的代码导致错误:

LoadError("main.jl", 24, MethodError(In[#undef, #undef, #undef, #undef, #undef], (1,), 0x0000000000006a05))

我想知道实现上有什么问题,希望知道其他方法来满足这里的需求。

您的代码试图将值分配给空引用。发生这种情况是因为 rows 的元素已初始化,您无法访问其 cols 字段。

的插图
o.rows(i).cols = Vector{Int}(undef,i);

你应该输入:

o.rows[i] = In(Vector{Int}(undef,i));

实际上构造函数中的整个代码可以缩短为:

Out(n) = new(n, [In(Vector{Int}(undef,i)) for i in 1:n])

也许是因为您的示例是更复杂的东西的精简版本,但是让您自己的结构来保存 Vectors 似乎有点过分了。我只是使用数组理解和一些方法来用虚拟值初始化,比如 zerozeros:

function make_jagged(::Type{T}, col_lengths...) where T
    [zeros(T, i) for i in col_lengths]
end

make_jagged(Int64, 2,5,3,6)
4-element Array{Array{Int64,1},1}:
 [0, 0]
 [0, 0, 0, 0, 0]
 [0, 0, 0]
 [0, 0, 0, 0, 0, 0]

如果您想坚持使用原始代码,请继续阅读。

您 运行 遇到的错误是因为它们限制了您访问未初始化的非 isbitstypes 的方式。 In 是一个非 isbitstype 因为它存储了一个可变的 cols 和一个指向内存中其他地方的指针。指向未初始化内存的指针是一个 悬空指针 ,因此为了您自己的(内存)安全,您不能获取它 o.rows[i] 或访问它的字段 o.rows[i].cols.

您可以对未初始化的非 isbitstype 元素执行的所有操作是为其设置一个适当的实例,例如:

# o.rows is a Vector{In}(undef,n)
    for i in 1:n
      o.rows[i] = In( Vector{Int}(undef,i) );
    end

谢谢你们。以下代码将适用于该任务:

struct JaggedMat{TT}
  nlen     :: Int;
  nlenvec  :: Vector{Int};
  rows     :: Vector{Vector{TT}};
end



function JaggedMat{TT}(n,nlenvec) where TT
  o = JaggedMat(n, nlenvec,Vector{Vector{TT}}(undef,n));
  
  
  for i in 1:n
    o.rows[i] = Vector{TT}(undef,max(nlenvec[i],1) );

    # initialization
    for j in 1:nlenvec[i]
      o.rows[i][j] = 0 ;
    end
    
  end
  
  return o

end



jagged_mat = JaggedMat{Float64}(3,Int[1,2,3])


如果您不介意使用外部包:


using PackedVectorsOfVectors

jagged_mat = PackedVectorsOfVectors.allocate_packed(Float64,undef,[1,2,3]

#filling with zeros:
#option one, by using package internals
jagged_mat.p .= 0.0

#option two, iterating:
for vector in jagged_mat
  vector .= 0.0
end

包的文档在这里https://synchronoustechnologies.github.io/PackedVectorsOfVectors.jl/stable/