arr_of_arr = Vector[[1],[2,3],[4,5]]
vcat(arr_of_arr...)That doesn’t quite seem to do what you want, Mauro:
julia> arr_of_arr = Vector{Int}[[1],[2,3],[4,5]]
3-element Array{Array{Int64,1},1}:
[1]
[2,3]
[4,5]
julia> vcat_nosplat(y) = eltype(y[1])[el[1] for el in y]
vcat_nosplat (generic function with 1 method)
julia> vcat_nosplat(arr_of_arr)
3-element Array{Int64,1}:
1
2
4
It’s quite trivial to achieve the desired result with only a few lines of code, though:
julia> function vcat_nosplat2(y)
result = Array(eltype(y[1]), 0)
sizehint!(result, sum(map(length, y))) #skip if iterating is more expensive than reallcoation
for a in y
for x in a
push!(result, x)
end
end
result
end
vcat_nosplat2 (generic function with 1 method)
julia> vcat_nosplat2(arr_of_arr)
5-element Array{Int64,1}:
1
2
3
4
5
// T
function vcat_nosplat2a(y)
result = Array(eltype(y[1]), 0)
for a in y
append!(result, a)
end
result
end
Using append! is definitely an improvement, thanks!
The reason I included the sizehint! call was that this resizes the vector once, and without requiring to copy any elements, and I assumed those saved copies would quickly win over having to iterate the collection an extra time to get the total number of elements. I’m glad to be proven wrong :)
function vcat_prealloc(y)
result = Array(eltype(y[1]), sum(map(length, y)))
for a in y
append!(result, a)
end
end
function vcat_dynamic(y)
result = Array(eltype(y[1]), 0)
for a in y
append!(result, a)
end
end
arr_of_arrs = Vector{Int}[rand(1:10, rand(1:10)) for _ in 1:10_000]
julia> @benchmark vcat_dynamic(arr_of_arrs)
================ Benchmark Results ========================
Time per evaluation: 441.11 μs [405.40 μs, 476.82 μs]
Proportion of time in GC: 0.00% [0.00%, 0.00%]
Memory allocated: 1.00 mb
Number of allocations: 16 allocations
Number of samples: 100
Number of evaluations: 100
Time spent benchmarking: 0.07 s
julia> @benchmark vcat_prealloc(arr_of_arrs)
================ Benchmark Results ========================
Time per evaluation: 716.85 μs [652.07 μs, 781.62 μs]
Proportion of time in GC: 0.00% [0.00%, 0.00%]
Memory allocated: 933.78 kb
Number of allocations: 7 allocations
Number of samples: 100
Number of evaluations: 100
Time spent benchmarking: 0.10 s
// T
For hcat, what shape would you want the output to have?
With your example input, the result of vcat is straightforward:
v = [[1],[2,3],[4,5]]
vcat(v...)
# -> [1, 2, 3, 4, 5]
But for hcat, what output would you want? hcat(v...) throws a DimensionMismatch error stating that vectors must have the same length.
//T
If they’re the same lengths, you could do vcat-then-reshape to get the same result as for hcat, but without splatting :)
reshape(fast_vcat(arr_of_arrs), length(arr_of_arrs[1]), length(arr_of_arrs))
// T