Julia:创建自定义类型的空/初始化多维数组

时间:2017-03-16 14:27:25

标签: multidimensional-array initialization julia compositetype type-constructor

我正在创建一个名为KeyVal的我自己的类型,如下所示:

type KeyVal
    first::Int
    second::Float64
end

我正在尝试在零矩阵上进行空/或初始化,其元素的类型为KeyVal。 通常使用其他类型

myMat = zeros(KeyVal, (10,3))

但这不起作用,因为没有为此复合类型定义zeros。所以我尝试用以下方式定义我自己的零函数:

import Base.zeros

function zeros(KeyVal,dims)
    if length(dims) > 1
        n=dims[1]
        m=dims[2]
        temp = repeat([KeyVal(0,0.0)], outer=m*n)
        temp = reshape(temp, (n,m))
        return temp
    elseif length(dims) == 1
        n=dims[1]
        temp= repeat([KeyVal(0,0.0)], outer=n)
        temp = reshape(temp, (n))
        return temp
    end
end

这会添加到之前定义的其他zeros的方法列表中。 但使用它会产生错误:

myMat = zeros(KeyVal, (N,M))

MethodError: no method matching zero(::Type{KeyVal})
Closest candidates are:
    .....

我想知道我是否可以某种方式解决这个问题,或者可能在类型构造函数中发出此信号,以便任何涉及类型KeyVal的数据结构都初始化为(first = 0,second = 0.0)。

以前我尝试将矩阵定义为:

myMat2 = Array{KeyVal,(N,M)}

这将创建矩阵,除了它的所有元素都是#undef,在这种情况下我无法访问myMat2的任何元素:

myMat2[1,1]
UndefRefError: access to undefined reference

1 个答案:

答案 0 :(得分:4)

您可以使用

创建任何类型T和尺寸N的未初始化数组
Array{T, N}(undef, dims...)

在一维和二维数组的特殊情况下,您可以使用别名VectorMatrix,例如,

julia> m = Matrix{KeyVal}(undef, 2,2)
2×2 Array{KeyVal,2}:
 #undef  #undef
 #undef  #undef

然后您可以照常设置元素,例如

m[1,2] = KeyVal(1,2)

如果您的类型有意义实现zero方法,则可以定义

Base.zero(::Type{KeyVal}) = KeyVal(0,0)

zeros将正常工作

julia> zeros(KeyVal, (2,2))
2×2 Array{KeyVal,2}:
 KeyVal(0,0.0)  KeyVal(0,0.0)
 KeyVal(0,0.0)  KeyVal(0,0.0)

警告:

zeros使用fill!,它使用同一实例的副本填充数组。相反,使用下面的理解或不包含引用的不可变类型(isbits为真)。后一种方法也可能更快,因为数组可以存储为一个连续的内存块。在这种情况下,您也可以直接使用fill(KeyVal(0,0), dims..),而不是定义zero。在0.6上,新的struct关键字默认创建一个不可变类型。

修改

另一种可能性是使用理解

julia> m = [KeyVal() for i=1:3, j=1:2]
3×2 Array{KeyVal,2}:
 KeyVal(0,0.0)  KeyVal(0,0.0)
 KeyVal(0,0.0)  KeyVal(0,0.0)
 KeyVal(0,0.0)  KeyVal(0,0.0)

为方便起见,我之前定义了外部构造函数

KeyVal() = KeyVal(0,0)