# How to "collapse" a Vector of Vector?

**URL:** <https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877>\
**Category:** New to Julia\
**Created:** [January 2, 2020, 3:05pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877 "2020-01-02T15:05:34Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![tomtom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomtom/32/5106_2.png) [@tomtom](https://discourse.julialang.org/u/tomtom)\
**Post date:** [January 2, 2020, 3:05pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877/1 "2020-01-02T15:05:35Z")

</div>

```julia
julia> vv = [[1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0] ]
3-element Array{Array{Float64,1},1}:
 [1.0, 2.0]     
 [3.0, 4.0, 5.0]
 [6.0, 7.0]     

```

is there an **efficient** way to transform it into:

```julia
[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]

```

?

thanks.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [January 2, 2020, 3:06pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877/2 "2020-01-02T15:06:48Z")

</div>

`reduce(vcat, vv)` is a simple way.

A lazy (and hence efficient) option would be `Iterators.flatten(vv)`.

```julia
julia> @btime reduce($vcat, $vv);
  53.095 ns (1 allocation: 144 bytes)

julia> @btime Iterators.flatten($vv);
  5.800 ns (1 allocation: 16 bytes)

julia> @btime collect(Iterators.flatten($vv));
  102.331 ns (4 allocations: 224 bytes)

```

There also is [RecursiveArrayTools.jl](https://github.com/JuliaDiffEq/RecursiveArrayTools.jl) which might be useful.

---

<div class="post-metadata">

**Author:** ![tomtom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomtom/32/5106_2.png) [@tomtom](https://discourse.julialang.org/u/tomtom)\
**Post date:** [January 2, 2020, 3:20pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877/3 "2020-01-02T15:20:34Z")

</div>

Thanks. `reduce()` seems to be quite efficient (and general).

Just curious if it is possible to be even more efficient than the `vvcat()` function defined below?

```julia
julia> function vvcat(vv)
           n = sum(length, vv)
           y = Vector{Float64}(undef, n)
           position = 1
           for i in Base.OneTo(length(vv) )
               curr = vv[i]
               l = length(curr)
               y[position:(position + l - 1)] = curr
               position += l
           end
           return y
       end
vvcat (generic function with 1 method)

julia> @btime vvcat($vv)
  49.657 ns (1 allocation: 144 bytes)
7-element Array{Float64,1}:
 1.0
 2.0
 3.0
 4.0
 5.0
 6.0
 7.0

julia> @btime reduce(vcat, $vv)
  52.273 ns (1 allocation: 144 bytes)
7-element Array{Float64,1}:
 1.0
 2.0
 3.0
 4.0
 5.0
 6.0
 7.0

```

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [January 2, 2020, 3:36pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877/4 "2020-01-02T15:36:50Z")

</div>

You can stick an `@inbounds` on the for loop to save some time for bounds checking.

---

<div class="post-metadata">

**Author:** ![tro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tro3/32/12355_2.png) [@tro3](https://discourse.julialang.org/u/tro3)\
**Post date:** [January 2, 2020, 4:19pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877/5 "2020-01-02T16:19:56Z")

</div>

Just for fun, I took a crack at further optimization and expanded generality (as I happen to need a function like this at the moment).

```julia
julia> function vvcat(vv::Vector{Vector{T}})::Vector{T} where T
           isempty(vv) && return []
           y = Vector{T}(undef, sum(length, vv))
           position = 1
           for curr in vv
               l = length(curr)
               @inbounds y[position:(position + l - 1)] = curr
               position += l
           end
           return y
       end
vvcat (generic function with 1 method)

julia> vv = [[1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0] ]
3-element Array{Array{Float64,1},1}:
 [1.0, 2.0]
 [3.0, 4.0, 5.0]
 [6.0, 7.0]

julia> @btime vvcat($vv); @btime reduce(vcat, $vv);
  39.858 ns (1 allocation: 144 bytes)
  47.065 ns (1 allocation: 144 bytes)

```

---

<div class="post-metadata">

**Author:** ![non-Jedi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/non-jedi/32/3645_2.png) [@non-Jedi](https://discourse.julialang.org/u/non-Jedi)\
**Post date:** [January 2, 2020, 4:26pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877/6 "2020-01-02T16:26:41Z")

</div>

> [@tro3](#):
>
> isempty(vv) && return

You probably want `isempty(vv) && return T[]` or you might see strange bugs from mixing `Any` arrays with `T` arrays in your program.

---

<div class="post-metadata">

**Author:** ![tro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tro3/32/12355_2.png) [@tro3](https://discourse.julialang.org/u/tro3)\
**Post date:** [January 2, 2020, 4:39pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877/7 "2020-01-02T16:39:10Z")

</div>

Thanks for the suggestion. I was assuming the final convert due to the output typing would take care of that, no? But still, I agree - better to remove the ambiguity.

---

<div class="post-metadata">

**Author:** ![non-Jedi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/non-jedi/32/3645_2.png) [@non-Jedi](https://discourse.julialang.org/u/non-Jedi)\
**Post date:** [January 2, 2020, 4:40pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877/8 "2020-01-02T16:40:42Z")

</div>

You’re right of course. My bad. 🙂 I don’t use function result type-annotations very often and glossed right over that.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 2, 2020, 6:33pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877/9 "2020-01-02T18:33:54Z")

</div>

This one is 30% faster on my computer:

```julia
function vvcat(vv::Vector{Vector{T}}) where {T}
    out = Vector{T}(undef, sum(length, vv))
    i = 0
    for v in vv, x in v
       @inbounds out[i+=1] = x
    end
    return out
end

```

---

<div class="post-metadata">

**Author:** ![tro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tro3/32/12355_2.png) [@tro3](https://discourse.julialang.org/u/tro3)\
**Post date:** [January 2, 2020, 6:36pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877/10 "2020-01-02T18:36:36Z")

</div>

Oh, very nice! I see the same. I am a Julia newbie, and that double-loop syntax does not yet spring to mind. Now I have some back-porting to do. 🙂 Thanks!

---

<div class="post-metadata">

**Author:** ![tro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tro3/32/12355_2.png) [@tro3](https://discourse.julialang.org/u/tro3)\
**Post date:** [January 2, 2020, 9:45pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877/11 "2020-01-02T21:45:01Z")

</div>

@DNF, do you agree that the `isempty(vv) && return T[]` is still required? Without it, I get `ERROR: ArgumentError: reducing over an empty collection is not allowed` from the `sum` reduction.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 2, 2020, 10:50pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877/12 "2020-01-02T22:50:49Z")

</div>

Yeah, I didn’t bother with the empty case, I wanted to focus on the point of handling one sample at the time.

You can either do the test, like you suggest, or you can replace

```julia
sum(length, vv)

```

with

```julia
mapreduce(length, +, vv; init=0)

```

which initializes the empty case to zero length.

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [January 5, 2020, 2:36pm UTC](https://discourse.julialang.org/t/how-to-collapse-a-vector-of-vector/32877/13 "2020-01-05T14:36:56Z")

</div>

Note that `reduce(vcat ,vv::AbstractVector{<:AbstractVector})` uses an optimized implementation essentially equivalent to `vcat(vv...)` (but which avoids the overhead of recompiling for each new number of entries in `vv`).
