2017-09-15 2 views
1

J'ai combiné des chaînes de caractères en utilisant une compréhension, mais cela m'a paru un peu maladroit.Julia: Comment joindre deux colonnes de chaîne d'une matrice ensemble

mymat = [collect('a':'z') collect('A':'Z')] 
[join(mymat[i,:]) for i in 1:size(mymat)[1]] 
+2

je ferais quelque chose comme 'mapslices (x -> "$ (x [1]) $ (x [2])", mymat, 2)', mais je ne peux pas dire c'est moins maladroit. –

+0

Je l'aime plus. Un de moins 'size (mymat) [1]'! – fsmart

+3

Si ça ne vous dérange pas que 'join' soit légèrement plus lent que' "$ (x [1]) $ (x [2])" '(parce que c'est plus général, bien sûr),' mapslices (join, mymat, 2) 'est beaucoup plus propre. –

Répondre

3

Il existe de nombreuses approches pour le faire. Conscient que vous joignez deux caractères, pas deux chaînes. La performance diffère dans une large gamme (1 à 79)

Sachant que le type de résultat diffère (matrice (26x1) ou le vecteur (26))

Préparation (en utilisant Julia 0.6.0.1)

mymat = [collect('a':'z') collect('A':'Z')] 
using BenchmarkTools 


@btime mapslices(join, mymat, 2) 
    79.372 μs (425 allocations: 15.63 KiB) 
    26×1 Array{String,2} 

@btime mapslices(x->"$(x[1])$(x[2])", mymat, 2) 
    32.144 μs (297 allocations: 10.78 KiB) 
    26×1 Array{String,2}: 

@btime [join(mymat[i,:]) for i in 1:size(mymat)[1]] 
    45.677 μs (212 allocations: 8.95 KiB) 
    26-element Array{String,1} 

@btime [join(mymat[i,:]) for i in 1:size(mymat, 1)] 
    44.494 μs (211 allocations: 8.92 KiB) 
    26-element Array{String,1} 

@btime [join(mymat[i,:]) for i in indices(mymat, 1)] 
    44.806 μs (211 allocations: 8.89 KiB) 
    26-element Array{String,1} 

@btime [join($mymat[i,:]) for i in indices($mymat, 1)] 
    44.806 μs (211 allocations: 8.89 KiB) 
    26-element Array{String,1} 

@btime [join($mymat[i,:]) for i in indices($mymat, 1)] 
    12.411 μs (211 allocations: 8.91 KiB) 
    26-element Array{String,1} 

@btime ["$(mymat[i,1])$(mymat[i,2])" for i in 1:size(mymat)[1]] 
    4.255 μs (32 allocations: 1.30 KiB) 
    26-element Array{String,1} 

@btime [string(mymat[i,1], mymat[i,2]) for i in 1:size(mymat)[1]] 
    4.157 μs (32 allocations: 1.30 KiB) 
    26-element Array{String,1} 

@btime [string($mymat[i,1],$mymat[i,1]) for i in indices($mymat, 1)] 
    1.080 μs (29 allocations: 1.20 KiB) 
    26-element Array{String,1} 

@btime string.(mymat[:,1], mymat[:,2]) 
    15.775 μs (56 allocations: 2.64 KiB) 
    26-element Array{String,1} 

@btime string.($mymat[:,1], $mymat[:,2]) 
    1.133 μs (31 allocations: 1.55 KiB) 
    26-element Array{String,1} 
+0

Astuce: vous pouvez (utiliser) 'size (mymat, 1)' au lieu de 'size (mymat) [1]', et en fait 'indices (mymat, 1)' généralité. En outre, interpolez les variables pour la macro '@ btime'. '@btime [chaîne ($ mymat [i, 1], $ mymat [i, 2]) pour i dans indices ($ mymat, 1)]' est presque cinq fois plus rapide avec le '$'. – DNF

+0

J'allais suggérer 'mymat [:, 1]. * Mymat [:, 2]' ou '@views mymat [:, 1]. * Mymat [:, 2]' mais je me suis rendu compte que '*' n'est pas défini pour 'Char's. Bizarre? – DNF

+0

Merci pour le conseil, j'ai ajouté de tels cas et compris un cas qui est 4 fois plus rapide que le précédent le plus rapide –

6

Vous pouvez utiliser mapslices pour cela:

julia> mapslices(join, mymat, 2) 
26×1 Array{String,2}: 
"aA" 
"bB" 
"cC" 
"dD" 
"eE" 
+3

Oh, whoops, je vois que @ Michael K. Borregaard et @ Fengyang Wang m'a battu dans les commentaires. Postez ceux comme réponses! –

+0

Le type de retour diffère de l'approche originale –