朱莉娅:不同类型的数组数组

6

我是 Julia 的新手,正在从 Python 转变过来。

所以,我想要构建在 Python 中我称之为“列表”的东西,由列表组成的列表。在我的情况下,这是一个由1000个元素组成的列表,每个元素都是3个列表构成的列表。

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

BIG_LIST = collect(Array{Int64,1}[[],[],[]] for i in 1:1000)

当最内层的三个列表都由整数组成时,这个代码可以满足我的要求。 现在我需要其中两个是整数,第三个是浮点数。 这可行吗?我该如何实现?

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

请注意,三个内部列表的长度相同,但在过程中可能会发生变化。

2个回答

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])
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   
 ([], [], [])   

以下是一些值得注意的细节:

  • 使用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)]
 []                         
 []                         
 []                         
 []                         
 []                         
 []                         
 []                         
 []                         

非常完整和有用的答案,非常感谢! - tidus95

5

Francois给你提供了一个很好的答案。我只想提出另外一种可能性。听起来你的数据结构相当复杂,但是具有特定的结构。例如,你的外层列表有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

我猜测,例如对于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)

记住,在Julia中使用自己的类型不会有性能惩罚。

另外,请注意,我在上面的函数中包含了所有类型信息,但实际上这并不是获取最大性能所必需的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接