Julia:具有不同类型的数组数组

tid*_*s95 6 arrays initialization list julia

Julia newbe 在这里,从 python 过渡。

所以,我想在 Python 中构建我称之为列表的东西,由列表组成的列表。就我而言,它是一个 1000 长的列表,其元素是 3 个列表的列表。

到目前为止,我是这样做的:

BIG_LIST = collect(Array{Int64,1}[[],[],[]] for i in 1:1000)
Run Code Online (Sandbox Code Playgroud)

当所有三个最内部的列表都由整数组成时,这符合我的目的。现在我需要其中 2 个是整数,而 Float 的第三个。这可能吗?我该怎么做?

如果您还可以更好地解释如何正确初始化这些对象,那就太好了。我知道 collect 不是这里的最佳选择。

请注意,3 个内部列表的长度在 3 个中相同,但在此过程中可能会有所不同。

ffe*_*tte 8

首先,如果您知道中间列表总是有 3 个元素,那么您最好使用这些元素的Tuple类型。元组可以独立指定其元素的类型。所以这样的事情可能适合你的目的:

julia> l = [(Int64[], Int64[], Float64[]) for _ in 1:10]
10-element Array{Tuple{Array{Int64,1},Array{Int64,1},Array{Float64,1}},1}:
 ([], [], [])
 ([], [], [])
 ([], [], [])
 ([], [], [])
 ([], [], [])
 ([], [], [])
 ([], [], [])
 ([], [], [])
 ([], [], [])
 ([], [], [])

julia> push!(l[1][3], 5)
1-element Array{Float64,1}:
 5.0

julia> l
10-element Array{Tuple{Array{Int64,1},Array{Int64,1},Array{Float64,1}},1}:
 ([], [], [5.0])
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   
Run Code Online (Sandbox Code Playgroud)

这里需要注意一些细节,您可能会感兴趣:

  • 可以使用 构造空但类型化的列表T[],其中T是元素类型。

  • collect(f(i) for i in 1:n)本质上相当于一个简单的理解(就像你在 python 中习惯的那样):[f(i) for i in 1:n]. 请注意,由于变量i在这里没有任何作用,您可以用_占位符替换它,以便读者更直接地看到您实际上是在创建类似对象的集合(但不完全相同,因为它们不共享)相同的底层内存;修改一个不会影响其他)。

  • 我不知道有什么更好的方法来初始化这样的集合,我不认为使用collect(或理解)在这里是一个坏主意。对于相同对象的集合,fill提供了一个有用的快捷方式,但它不适用于这里,因为所有子列表都将被链接。




现在,如果所有内部子列表的长度相同,您可能希望切换到稍微不同的数据结构:元组向量的向量:

julia> l2 = [Tuple{Int64,Int64,Float64}[] for _ in 1:10]
10-element Array{Array{Tuple{Int64,Int64,Float64},1},1}:
 []
 []
 []
 []
 []
 []
 []
 []
 []
 []

julia> push!(l2[2], (1,2,pi))
1-element Array{Tuple{Int64,Int64,Float64},1}:
 (1, 2, 3.141592653589793)

julia> l2
10-element Array{Array{Tuple{Int64,Int64,Float64},1},1}:
 []                         
 [(1, 2, 3.141592653589793)]
 []                         
 []                         
 []                         
 []                         
 []                         
 []                         
 []                         
 []                         
Run Code Online (Sandbox Code Playgroud)


Col*_*ers 5

弗朗索瓦给了你一个很好的答案。我只是想提出另一种可能性。听起来您的数据具有相当复杂但具体的结构。例如,你的外部列表有 1000 个元素,而你的内部列表总是有 3 个列表......

有时在这些情况下,构建自己的类型并编写几个访问器函数会更直观。这样你就不会最终做一些事情,比如mylist[3][2][6]忘记哪个索引指的是你的数据的哪个维度。例如:

struct MyInnerType
    field1::Vector{Int}
    field2::Vector{Int}
    field3::Vector{Float64}
end
struct MyOuterType
    x::Vector{MyInnerType}
    function MyOuterType(x::Vector{MyInnerType})
        length(x) != 1000 && error("This vector should always have length of 1000")
        new(x)
    end
end
Run Code Online (Sandbox Code Playgroud)

我在这里猜测,但也许像这样的访问器函数对例如field3

get_field3(y::MyInnerType, i::Int)::Float64 = y.field3[i]
get_field3(z::MyOuterType, iouter::Int, iinner::Int)::Float64 = get_field3(z.x[iouter], iinner)
Run Code Online (Sandbox Code Playgroud)

请记住,在 Julia 中使用您自己的类型没有性能损失。

另一件事,为了清楚起见,我在上面的函数中包含了所有类型信息,但这实际上也不是获得最大性能所必需的。