在Julia中,vec
函数可以将多维数组转换为一维数组。
但对于数组的数组或数组的元组它不起作用。
除了使用数组推导之外,还有其他方法可以展平数组的数组/元组吗?或者是数组的数组/元组的数组/元组吗?或者……
Iterators.flatten(x)
创建一个生成器,可以迭代遍历 x
的每个元素。它可以处理一些你所描述的情况,例如:
Iterators.flatten(x)
创建一个生成器,可以迭代遍历 x
的每个元素。它可以处理一些你所描述的情况,例如:
julia> collect(Iterators.flatten([(1,2,3),[4,5],6]))
6-element Array{Any,1}:
1
2
3
4
5
6
如果你有嵌套了多层数组和元组的数据结构,那么你应该重新考虑你的数据结构,因为它听起来不稳定。但是,你可以使用多个调用 flatten
来处理,例如:
julia> collect(Iterators.flatten([(1,2,[3,3,3,3]),[4,5],6]))
6-element Array{Any,1}:
1
2
[3, 3, 3, 3]
4
5
6
julia> collect(Iterators.flatten(Iterators.flatten([(1,2,[3,3,3,3]),[4,5],6])))
9-element Array{Any,1}:
1
2
3
3
3
3
4
5
6
请注意,我的所有示例都返回一个Array{Any,1}
。这对性能来说是一个不好的迹象,因为它意味着编译器无法为输出数组的元素确定单个具体类型。我选择这些示例是因为我读到你的问题时觉得你可能已经有了类型不稳定的容器。
要将一个数组的数组展平,可以简单地使用vcat()函数,如下所示:
julia> A = [[1,2,3],[4,5], [6,7]]
Vector{Int64}[3]
Int64[3]
Int64[2]
Int64[2]
julia> flat = vcat(A...)
Int64[7]
1
2
3
4
5
6
7
最简单的方法是两次应用省略号...
。
A = [[1,2,3],[4,5], [6,7]]
flat = [(A...)...]
println(flat)
输出结果将会是[1, 2, 3, 4, 5, 6, 7]
。
x = [rand(n) for n in rand(1:20, 100000)]
。比较一下 @btime [(x...)...]
(21.215毫秒和1049049次分配)和@btime vcat(x...)
(2.836毫秒和3次分配)的区别。 - MentatOfDuneVectorOfArray
,它会使用索引回退来为VectorOfArray
A
提供convert(Array,A)
。请注意保留HTML标记。julia> using RecursiveArrayTools
julia> A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
3-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
julia> VA = VectorOfArray(A)
3-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
首先,它作为一个懒惰的包装器来执行索引而不进行转换:
julia> VA[1,3]
7
julia> convert(Array,VA)
3×3 Array{Int64,2}:
1 4 7
2 5 8
3 6 9
hcat(A...)
的操作,但如果您要拆分很多数组,则速度会很慢!现在,您可能会想:编写一个预先分配矩阵的函数,然后遍历并填充它怎么样?这几乎就是VectorOfArray
上的convert
所做的,除了convert
在此处使用的回退利用了Tim Holy的Cartesian机制。曾经,我写过那个函数:function vecvec_to_mat(vecvec)
mat = Matrix{eltype(eltype(vecvec))}(length(vecvec),length(vecvec[1]))
for i in 1:length(vecvec)
mat[i,:] .= vecvec[i]
end
mat
end
但是我后来放弃了它,因为备选方案更快。因此,YMMV,但这是解决你问题的几种方式。
针对Julia 0.7x:
针对数组:
flat(arr::Array) = mapreduce(x -> isa(x, Array) ? flat(x) : x, append!, arr,init=[])
针对元组:
flat(arr::Tuple) = mapreduce(x -> isa(x, Tuple) ? flat(x) : x, append!, arr,init=[])
适用于任意深度。 请参见:https://rosettacode.org/wiki/Flatten_a_list#Julia 数组/元组的代码:
function flatten(arr)
rst = Any[]
grep(v) = for x in v
if isa(x, Tuple) || isa(x, Array)
grep(x)
else push!(rst, x) end
end
grep(arr)
rst
end
Iterators
已经内置在基础库中了,旧的Iterators
包已经不推荐使用。如果你现在安装它,我不知道会发生什么,但如果有任何问题就卸载它。你需要使用using Base.Iterators
来获取导出的方法(包括flatten
),或者使用import Base.Iterators: flatten
来仅获取一个方法。 - gggg6元素Vector{Int64}
。 - rashid