在我所拥有的程序中,我希望用Nothing初始化一组矩阵,然后如果满足某些条件,将单个元素更改为Bool或String类型的值。
当我初始化时,这很好。
Array{Union{Nothing,Bool},2}(undef,5,5)会产生类似的结果
5×5 Matrix{Union{Nothing, Bool}}:
nothing nothing nothing nothing nothing
nothing nothing nothing nothing nothing
nothing nothing nothing nothing nothing
nothing nothing nothing nothing nothing
nothing nothing nothing nothing nothing但当我初始化的时候
Array{Union{Nothing,String},2}(undef,5,5)这给了我
5×5 Matrix{Union{Nothing, String}}:
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef现在,我可以将第二个数组中的值更改为Strings,这样我就可以
5×5 Matrix{Union{Nothing, String}}:
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef "Look"
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef但是当我将第二个大数组构造为
Array{Union{Nothing, Bool, String}}(undef,10,5)看起来就像
10×5 Matrix{Union{Nothing, Bool, String}}:
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef我可以很高兴地将前5行分配给由Nothing和Bool构造的第一个数组,但不能分配给由#undef/nothing和String构造的第二个矩阵。相反,我得到了这个错误
UndefRefError: access to undefined reference起初,我认为这与从类型Nothing或#undef转换为String有关,但当我在上面分配单独的字符串时,我似乎能够做到这一点。
有什么想法吗?
发布于 2021-09-16 17:02:11
首先让我先给出一个建议,做些什么。
一般来说,最好以以下方式创建矩阵:
julia> Array{Union{Nothing,String},2}(nothing,5,5)
5×5 Matrix{Union{Nothing, String}}:
nothing nothing nothing nothing nothing
nothing nothing nothing nothing nothing
nothing nothing nothing nothing nothing
nothing nothing nothing nothing nothing
nothing nothing nothing nothing nothing通过这种方式,您可以确保它们被正确初始化。
现在来解释你所观察到的。#undef而不是nothing不是一个值。这意味着矩阵中的给定单元格不连接到任何值。您不能从这样的单元格中读取。你必须先给它写信,然后才能读到:
julia> x = Vector{String}(undef, 3)
3-element Vector{String}:
#undef
#undef
#undef
julia> x[1]
ERROR: UndefRefError: access to undefined reference
Stacktrace:
[1] getindex(A::Vector{String}, i1::Int64)
@ Base .\array.jl:801
[2] top-level scope
@ REPL[6]:1
julia> x[1] = "a"
"a"
julia> x
3-element Vector{String}:
"a"
#undef
#undef
julia> x[1]
"a"您可能会问,为什么对于Union{Bool, Nothing}元素类型,您在数组中得到一个值,而在Union{String, Nothing}情况下,您得到的是#undef,即没有您可以读取的值。
答案是,朱莉娅有两种类型:
Bool
isbitstype函数返回true;这些数据是不可变的,不包含对其他值的引用;这类数据的示例是
String (从技术上来说,字符串表示为对存储字符串内容的内存中某个位置的引用)。
如你所见:
julia> isbitstype(Bool)
true
julia> isbitstype(String)
false现在-如果您的数组要存储一个位类型(或它们的联合),那么它直接存储它,所以总是有一些值(不能保证它是什么值,但您知道您会得到一个值),例如:
julia> Matrix{Int}(undef, 5, 5)
5×5 Matrix{Int64}:
260255120 260384864 260235344 260254240 0
260254240 260235344 260235344 260255120 0
261849744 260235344 260235344 260235344 0
260465792 260465440 260464224 260235344 0
260235344 260235344 260235344 260235344 0正如您所看到的,我们在它中存储了一些值,但是它没有定义值是什么。
另一方面,如果数组要存储非位类型,它实际上存储对值的引用。这意味着当您在没有初始化的情况下创建这样的值数组时,就会得到#undef --这意味着在这个单元格中没有对有效值的引用。
为了向您展示它与字符串没有直接关系,让我向您展示String7类型(例如,它是由CSV.jl导出的),它是一个固定宽度字符串(最大宽度为7个字节),它是位类型。观察差异:
julia> using CSV
julia> isbitstype(String7)
true
julia> Matrix{String7}(undef, 5, 5)
5×5 Matrix{String7}:
"\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" … "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0"
"\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0"
"\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0"
"\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0"
"\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0" "\0\0\0\0\x0f\x86_\x10\0\0\0\0\0\0\0\0"
julia> Matrix{String}(undef, 5, 5)
5×5 Matrix{String}:
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef
#undef #undef #undef #undef #undef在第一种情况下,您得到了一个被初始化的String7值矩阵,但是它初始化为的值是未定义的(它是一些垃圾)。在第二种情况下,您得到了一个String值的矩阵,由于它们是非位的,所以矩阵是未初始化的--它还没有保存任何值。首先,您必须指定一些值,然后才能读取它们。
最后,有一个isassigned函数,它允许您检查容器是否有一个与某个索引相关联的值(即检查它是否不是#undef或索引是否超出范围)。下面是一个示例:
julia> x = Vector{String}(undef, 3)
3-element Vector{String}:
#undef
#undef
#undef
julia> x[1] = "a"
"a"
julia> isassigned(x, 1) # we have a value here
true
julia> isassigned(x, 2) # no value
false
julia> isassigned(x, 3) # no value
false
julia> isassigned(x, 4) # out of bounds
false如果有什么不清楚的地方,请发表评论,我可以扩展答案。
https://stackoverflow.com/questions/69211745
复制相似问题