Julia - 创建 Union{Nothing,String} 与 Union{Nothing,Bool} 的矩阵

Pab*_*blo 4 julia

在我的程序中,我想初始化一堆矩阵,Nothing然后如果满足某些条件,则将单个元素更改为类型Bool或的值String

\n

当我初始化时这工作正常

\n
Array{Union{Nothing,Bool},2}(undef,5,5)\n
Run Code Online (Sandbox Code Playgroud)\n

这会产生类似的东西

\n
5\xc3\x975 Matrix{Union{Nothing, Bool}}:\n nothing  nothing  nothing  nothing  nothing\n nothing  nothing  nothing  nothing  nothing\n nothing  nothing  nothing  nothing  nothing\n nothing  nothing  nothing  nothing  nothing\n nothing  nothing  nothing  nothing  nothing\n
Run Code Online (Sandbox Code Playgroud)\n

但当我初始化时不是

\n
Array{Union{Nothing,String},2}(undef,5,5)\n
Run Code Online (Sandbox Code Playgroud)\n

这给了我

\n
5\xc3\x975 Matrix{Union{Nothing, String}}:\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n
Run Code Online (Sandbox Code Playgroud)\n

现在我可以将第二个数组中的值更改为Strings 以便我得到

\n
5\xc3\x975 Matrix{Union{Nothing, String}}:\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef     "Look"\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n
Run Code Online (Sandbox Code Playgroud)\n

但是当我将第二个大数组构造为

\n
Array{Union{Nothing, Bool, String}}(undef,10,5)\n
Run Code Online (Sandbox Code Playgroud)\n

看起来像

\n
10\xc3\x975 Matrix{Union{Nothing, Bool, String}}:\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n
Run Code Online (Sandbox Code Playgroud)\n

Nothing我可以很高兴地将前 5 行分配给由和构造的第一个数组Bool,但我无法分配给由#undef/nothing和构造的第二个矩阵String构造的第二个矩阵。相反,我收到此错误

\n
UndefRefError: access to undefined reference\n
Run Code Online (Sandbox Code Playgroud)\n

最初我认为这与从类型转换Nothing#undefString但当我在上面分配单个字符串时,我似乎能够做到这一点。

\n

有任何想法吗?

\n

Bog*_*ski 7

首先让我从一个建议开始,即做什么。

\n

一般来说,最好按以下方式创建矩阵:

\n
julia> Array{Union{Nothing,String},2}(nothing,5,5)\n5\xc3\x975 Matrix{Union{Nothing, String}}:\n nothing  nothing  nothing  nothing  nothing\n nothing  nothing  nothing  nothing  nothing\n nothing  nothing  nothing  nothing  nothing\n nothing  nothing  nothing  nothing  nothing\n nothing  nothing  nothing  nothing  nothing\n
Run Code Online (Sandbox Code Playgroud)\n

通过这种方式,您可以确保它们已正确初始化。

\n

现在解释一下你所观察到的情况。#undef相反,nothing不是一个值。这意味着矩阵中的给定单元未连接到任何值。您无法从这样的单元格中读取内容。您必须先写入它,然后才能读取它:

\n
julia> x = Vector{String}(undef, 3)\n3-element Vector{String}:\n #undef\n #undef\n #undef\n\njulia> x[1]\nERROR: UndefRefError: access to undefined reference\nStacktrace:\n [1] getindex(A::Vector{String}, i1::Int64)\n   @ Base .\\array.jl:801\n [2] top-level scope\n   @ REPL[6]:1\n\njulia> x[1] = "a"\n"a"\n\njulia> x\n3-element Vector{String}:\n    "a"\n #undef\n #undef\n\njulia> x[1]\n"a"\n
Run Code Online (Sandbox Code Playgroud)\n

您可能会问为什么对于元素类型的情况,您会在数组中获得一个值,而在您确实 getUnion{Bool, Nothing}的情况下,即没有您可以读取的值。Union{String, Nothing}#undef

\n

答案是,在 Julia 中有两种类型:

\n
    \n
  • 位类型,isbitstype函数返回true;此类数据是不可变的,并且不包含对其他值的引用;此类数据的一个例子是Bool
  • \n
  • 非位类型,要么是可变的,要么包含引用;此类数据的一个示例是String(因为从技术上讲,字符串表示为对存储字符串内容的内存中某个位置的引用)
  • \n
\n

正如你在这里看到的:

\n
julia> isbitstype(Bool)\ntrue\n\njulia> isbitstype(String)\nfalse\n
Run Code Online (Sandbox Code Playgroud)\n

现在 - 如果您的数组要存储位类型(或其联合),那么它会直接存储它,因此总是有一些值(不能保证它是什么值,但您知道您会得到一个值),例如:

\n
julia> Matrix{Int}(undef, 5, 5)\n5\xc3\x975 Matrix{Int64}:\n 260255120  260384864  260235344  260254240  0\n 260254240  260235344  260235344  260255120  0\n 261849744  260235344  260235344  260235344  0\n 260465792  260465440  260464224  260235344  0\n 260235344  260235344  260235344  260235344  0\n
Run Code Online (Sandbox Code Playgroud)\n

正如您所看到的,我们存储了一些值,但未定义这些值是什么。

\n

另一方面,如果您的数组要存储非位类型,它实际上存储对值的引用。这意味着当您创建此类值的数组而不对其进行初始化时,您会得到#undef- 这意味着在此单元格中没有对有效值的引用。

\n

只是为了向您展示它与字符串没有直接关系,让我向您展示例如类型String7(例如通过 CSV.jl 导出),它是一个固定宽度字符串(最大宽度为 7 个字节),是一种位类型。观察差异:

\n
julia> using CSV\n\njulia> isbitstype(String7)\ntrue\n\njulia> Matrix{String7}(undef, 5, 5)\n5\xc3\x975 Matrix{String7}:\n "\\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"  \xe2\x80\xa6  "\\0\\0\\0\\0\\x0f\\x86_\\x10\\0\\0\\0\\0\\0\\0\\0\\0"\n "\\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"\n "\\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"\n "\\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"\n "\\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"\n\njulia> Matrix{String}(undef, 5, 5)\n5\xc3\x975 Matrix{String}:\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n #undef  #undef  #undef  #undef  #undef\n
Run Code Online (Sandbox Code Playgroud)\n

在第一种情况下,您得到了一个String7已初始化的值矩阵,但它初始化为的值未定义(这是一些垃圾)。\n在第二种情况下,您得到了一个String值矩阵,并且由于它们是非位,因此矩阵未初始化 - 它尚未保存任何值。您首先必须分配一些值,然后才能读取它们。

\n

最后,有一个isassigned函数允许您检查容器是否具有与某个索引关联的值(即检查是否没有#undef或索引是否超出范围)。这是一个例子:

\n
julia> x = Vector{String}(undef, 3)\n3-element Vector{String}:\n #undef\n #undef\n #undef\n\njulia> x[1] = "a"\n"a"\n\njulia> isassigned(x, 1) # we have a value here\ntrue\n\njulia> isassigned(x, 2) # no value\nfalse\n\njulia> isassigned(x, 3) # no value\nfalse\n\njulia> isassigned(x, 4) # out of bounds\nfalse\n
Run Code Online (Sandbox Code Playgroud)\n

如果有任何不清楚的地方请评论,我可以扩展答案。

\n