Create a vector from n different vectors

question

#1

How do i create a vector from n different vectors in a while loop?


#2

Please explain more clearly what you want to do and show what you have already tried that didn’t work.


#3

You probably want append!


#4

First of all, you should probably start by reading the documentation on arrays. This will tell you mostly everything you need to know to work with them.

For your particular question, you want vcat, which concatenates arrays along the 1st dimension. If you have n vectors in an array of vectors vectors, you might do this:

new_vec = Vector{T}()
for vec in vectors
    new_vec = vcat(new_vec, vec)
end

Instead of vcat(new_vec, vec), you can also write [new_vec; vec] as a convenient shorthand.

Edit: You could write this more concisely using a functional pattern (arguably more idiomatic):

new_vec = foldr(vcat, vectors)

#5

new_vec = vcat(new_vec, vec)

This is a bad idea, since you are creating a new vector each time. As @cortner suggested, use append! instead.


#6

Good point. I guess I’m a little too fond of one-line solutions.


#7

Actually I think you can use vcat but you need to splice, i.e.

new_vec = vcat(vectors...)

Quick benchmark:

julia> vectors = [rand(3) for i in 1:100];

julia> @benchmark vcat($vectors...)
BenchmarkTools.Trial: 
  memory estimate:  2.50 kb
  allocs estimate:  1
  --------------
  minimum time:     1.535 μs (0.00% GC)
  median time:      1.682 μs (0.00% GC)
  mean time:        2.388 μs (20.96% GC)
  maximum time:     585.015 μs (85.50% GC)
  --------------
  samples:          10000
  evals/sample:     10
  time tolerance:   5.00%
  memory tolerance: 1.00%

versus:

julia> @benchmark foldr(vcat, $vectors)
BenchmarkTools.Trial: 
  memory estimate:  131.63 kb
  allocs estimate:  99
  --------------
  minimum time:     19.002 μs (0.00% GC)
  median time:      21.491 μs (0.00% GC)
  mean time:        42.924 μs (40.05% GC)
  maximum time:     3.319 ms (98.25% GC)
  --------------
  samples:          10000
  evals/sample:     1
  time tolerance:   5.00%
  memory tolerance: 1.00%

I imagine that the vcat implemented with many arguments preallocates the output and avoids creating N-1 intermediate arrays.


#8

Cool, I thought there should be a clean way to write this so that the compiler could optimize it.


#9

I would like to take the opportunity to plug Compat.Iterators.flatten;

julia> using Compat.Iterators

julia> collect(flatten([rand(3) for i in 1:100]))
300-element Array{Float64,1}:
 0.320838   
 0.683946   
 0.119694   
 0.317296   
 0.686963   
 0.912702   
 0.602305   
 0.681549   
 0.814596   
 0.251851   
 ⋮          
 0.311022   
 0.000653191
 0.214496   
 0.489029   
 0.040118   
 0.848041   
 0.480453   
 0.384383   
 0.0319383  

collect(flatten(vects)) is the way to do it in Base.

Note that this is equivalent to [x for xs in xss for x in xs] which effectively lowers to collect(flatten(xss)).


#10

Cool, I thought there should be a clean way to write this so that the compiler could optimize it.

Worth keeping in mind that what the compiler can optimize and what’s optimal are not necessarily the same thing. Splatting lots of arguments can sometimes introduce problems you wouldn’t have without splatting.