web-dev-qa-db-fra.com

Julia: Aplatissement du tableau de tableau / tuples

Dans Julia vec remodèle les tableaux multidimensionnels en tableaux à une dimension. Cependant, cela ne fonctionne pas pour les tableaux de tableaux ou les tableaux de tuples. En plus d'utiliser la compréhension des tableaux, existe-t-il une autre façon d'aplatir les tableaux de tableaux/tuples? Ou des tableaux de tableaux/tuples de tableaux/tuples? Ou ...

11
Pigna

Iterators.flatten(x) crée un générateur qui itère sur chaque élément de x. Il peut gérer certains des cas que vous décrivez, par exemple

Julia> collect(Iterators.flatten([(1,2,3),[4,5],6]))
6-element Array{Any,1}:
 1
 2
 3
 4
 5
 6

Si vous avez des tableaux de tableaux de tableaux et de tuples, vous devriez probablement reconsidérer votre structure de données car elle ne semble pas de type stable. Cependant, vous pouvez utiliser plusieurs appels à flatten, par exemple

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

Notez comment tous mes exemples retournent un Array{Any,1}. C'est un mauvais signe pour les performances, car cela signifie que le compilateur n'a pas pu déterminer un seul type concret pour les éléments du tableau de sortie. J'ai choisi ces exemples parce que la façon dont j'ai lu votre question, il semblait que vous ayez peut-être déjà des conteneurs instables de type.

11
gggg

Si vous utilisez VectorOfArray de RecursiveArrayTools.jl , il utilise le repli d'indexation pour fournir convert(Array,A) pour un VectorOfArrayA.

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]

Le premier agit comme un wrapper paresseux pour faire l'indexation sans conversion:

Julia> VA[1,3]
7

Notez que les colonnes sont des tableaux séparés, de sorte que c'est toujours "majeur de colonne" (c'est-à-dire efficace pour indexer les colonnes). Mais alors il a une conversion directe:

Julia> convert(Array,VA)
3×3 Array{Int64,2}:
 1  4  7
 2  5  8
 3  6  9

L'autre façon de gérer cette conversion est de faire quelque chose comme hcat(A...), mais c'est lent si vous avez beaucoup de tableaux que vous éclaboussez!

Maintenant, vous pouvez penser: qu'en est-il de l'écriture d'une fonction qui pré-alloue la matrice, puis la boucle et la remplit? C'est presque ce que convert sur le VectorOfArray fonctionne, sauf que la solution de repli que convert utilise ici utilise la machinerie cartésienne de Tim Holy. À un moment donné, j'ai écrit cette fonction:

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

mais je m'en suis débarrassé depuis car le repli a été beaucoup plus rapide. Donc, YMMV mais c'est quelques façons de résoudre votre problème.

5
Chris Rackauckas

Afin d'aplatir un tableau de tableaux, vous pouvez simplement utiliser vcat () comme ceci:

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
4
aggharta

pour Julia 0.7x:

pour les tableaux:

flat (arr :: Array) = mapreduce (x -> isa (x, Array)? flat (x): x, append !, arr, init = [])

pour Tuples:

flat (arr :: Tuple) = mapreduce (x -> isa (x, Tuple)? flat (x): x, append !, arr, init = [])

Fonctionne pour une profondeur arbitraire. voir: https://rosettacode.org/wiki/Flatten_a_list#Julia Code pour tableau/tuple:

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
0
Ultima Ratio