# Very best way to concatenate an array of arrays

**URL:** <https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672>\
**Category:** General Usage\
**Tags:** arrays\
**Created:** [January 29, 2018, 3:29pm UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672 "2018-01-29T15:29:50Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)\
**Post date:** [January 29, 2018, 3:29pm UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/1 "2018-01-29T15:29:50Z")

</div>

I’ve been wondering about this for a while. Suppose I want to concatenate arrays of arrays. Currently the only way I know of doing that is `vcat(A...)` (or could be `hcat`, whatever). My understanding is that this is doubly inefficient, first because it has to allocate a new array (unavoidable), but second because it has to recompile `vcat` for every number of arguments and every element type of every input array `A`. Therefore, if you want to do this lots of times on lots of different arrays you are really screwed. I suppose I could just write a function that takes a `Vector{<:AbstractVector}` and allocates the new array properly, but that seems silly.

What is the very best way of doing this?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [January 29, 2018, 3:39pm UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/2 "2018-01-29T15:39:42Z")

</div>

> [@ExpandingMan](#):
>
> What is the very best way of doing this?

```julia
using RecursiveArrayTools
VA = VectorOfArray(A)
arr = convert(Array,VA)

```

`VectorOfArray` is a lazy representation of the array of arrays as a higher order tensor (/matrix if `A` is a vector of vectors). It uses the indexing fallback to do the conversion. Honestly, I tried writing my own loop for the conversion but the fallback was faster (Tim Holy Cartesian magic?) so this is what I’ve found to be the fastest, and I don’t know how to recreate it without using the lazy matrix indexing.

---

<div class="post-metadata">

**Author:** ![improbable22](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/improbable22/32/5464_2.png) [@improbable22](https://discourse.julialang.org/u/improbable22)\
**Post date:** [January 29, 2018, 4:27pm UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/3 "2018-01-29T16:27:46Z")

</div>

Thanks, RecursiveArrayTools looks useful.

I was doing this with a little function in Flux.jl, and a quick test shows it’s sometimes quicker:

```julia
A100 = [rand(100) for i=1:100];
using BenchmarkTools

using RecursiveArrayTools
@btime convert(Array,VectorOfArray(A100)); # 25.571 μs

using Flux: batch
@btime batch(A100); # 10.686 μs

maximum( convert(Array,VectorOfArray(A100)) - batch(A100) ) # zero

```

But for `[rand(10) for i=1:1000]` this is reversed.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [January 29, 2018, 4:34pm UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/4 "2018-01-29T16:34:02Z")

</div>

I was stupid and thought vcat with single arg would do the job. It doesn’t.

Whether to be lazy or not kinda depends on how often you plan to access the new array, how much memory you have available and how cache-friendly your planned access is.

---

<div class="post-metadata">

**Author:** ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)\
**Post date:** [January 29, 2018, 4:44pm UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/5 "2018-01-29T16:44:03Z")

</div>

`vcat(V)` just returns `V`.

Wow, ok I was kind of expecting that by now there’d be a really straightforward answer to this. It’s probably too late now, but shouldn’t there be something in `Base` that does this? I’m thinking of a function that simply allocates an array with elements type the union of the arguments. It would have to do inefficient allocation, but at least it wouldn’t have the compile penalties of `vcat`.

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [January 29, 2018, 4:46pm UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/6 "2018-01-29T16:46:54Z")

</div>

See discussion here:

[https://github.com/JuliaLang/julia/issues/21672](https://github.com/JuliaLang/julia/issues/21672)

I think the consensus was to implement an efficient `reduce(vcat, v)` but I think it hasn’t been done yet. It is a performance improvement so should be non-breaking.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 29, 2018, 5:42pm UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/7 "2018-01-29T17:42:46Z")

</div>

> [@ExpandingMan](#):
>
> It’s probably too late now, but shouldn’t there be something in Base that does this?

There seems to be a fairly common misunderstanding about how compatibility works and what is “too late” after 1.0 is released: you can add new features, including new exported names in 1.x since that does not break older code. What you cannot do is remove or change existing features in a 1.x version.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 29, 2018, 7:33pm UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/8 "2018-01-29T19:33:07Z")

</div>

Note also that a faster `reduce(vcat, arrays)` method can be added at any time, regardless of feature freezes, since it is just an optimization.

---

<div class="post-metadata">

**Author:** ![harven](https://avatars.discourse-cdn.com/v4/letter/h/3da27b/32.png) [@harven](https://discourse.julialang.org/u/harven)\
**Post date:** [January 30, 2018, 10:54am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/9 "2018-01-30T10:54:29Z")

</div>

In a slightly more general setting, I have used the following to map and concat an array of array.

```
mapconcat1(f, v) = [z for x in v for z in f(x)]
mapconcat2(f, v) = vcat(f.(v)...)
mapconcat3(f,v) = mapfoldl(f, append!, [], v)

```

The first one allocates more but in some cases it was faster than the other two. I guess it depends on the shape of the data.

---

<div class="post-metadata">

**Author:** ![sdmcallister](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdmcallister/32/2324_2.png) [@sdmcallister](https://discourse.julialang.org/u/sdmcallister)\
**Post date:** [January 31, 2018, 12:55am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/10 "2018-01-31T00:55:03Z")

</div>

Maybe I’m missing the intent of the question, but I normally write an ugly function similar to this:

```julia
function vec2array(v)
    r = length(v)
    c = length(v[1])
    a = Array{Int64}(r,c)
    for i in 1:r, j in 1:c
        a[i,j] = v[i][j]
    end
    a
end

```

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [January 31, 2018, 1:20am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/11 "2018-01-31T01:20:35Z")

</div>

In Common Lisp, the equivalent of

```julia
foo(args...) = args
a = [1,2,3]
foo(a...) === a

```

is true. It’s a very good optimization. I wonder how breaking it would be to sometimes pass varargs as arrays instead of tuples (and how complicated it would be to optimize in a language with multiple dispatch).

---

<div class="post-metadata">

**Author:** ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)\
**Post date:** [January 31, 2018, 1:47am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/12 "2018-01-31T01:47:55Z")

</div>

> [@cstjean](#):
>
> I wonder how breaking it would be to sometimes pass varargs as arrays instead of tuples

I don’t think we’d even need anything like that would we? All I had in mind when posting this thread was something roughly like @sdmcallister suggested being in `Base`. The only complication I can think of is determining the appropriate `Union` type for the resulting array. I suppose we’d have to be consistent with the typing behavior of `vcat`.

By the way, as far as I know even `StaticArray`s are basically just tuples under the hood, so that would seem to suggest that yes, arguments really do need to be passed as tuples.

---

<div class="post-metadata">

**Author:** ![kolia](https://avatars.discourse-cdn.com/v4/letter/k/c68b51/32.png) [@kolia](https://discourse.julialang.org/u/kolia)\
**Post date:** [January 18, 2019, 9:02pm UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/13 "2019-01-18T21:02:01Z")

</div>

The lazy `Hcat` and `Vcat` functions in:

> **[GitHub - JuliaArrays/LazyArrays.jl: Lazy arrays and linear algebra in Julia](https://github.com/JuliaArrays/LazyArrays.jl)**
>
> Lazy arrays and linear algebra in Julia. Contribute to JuliaArrays/LazyArrays.jl development by creating an account on GitHub.

do exactly what you want, as far as I understand: they are a lazy / no-copy wrapper around the arrays that behave like the concatenation, including non-scalar indexing and broadcasting.

```julia
using LazyArrays
a = Vcat(1:5, 1:6)

# non-scalar
a[2:5]
a[[1,3,9]]

# broadcast
a .* rand(11,2)
a .- Vcat(1:7, 1:4)

```

RecursiveArrayTools’ `ArrayPartition`s has similar functionality, but does not currently support non-scalar indexing `a[[2,4,5]]`, and only broadcasts with other `ArrayPartition`s that have the same underlying sub-vector sizes, whereas `LazyArrays`’ `Hcat` and `Vcat` will broadcast with just about anything afaict.

Haven’t compared performance though.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [January 19, 2019, 4:30am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/14 "2019-01-19T04:30:18Z")

</div>

> [@kolia](#):
>
> RecursiveArrayTools’ `ArrayPartition` s has similar functionality, but only supports single-integer indexing `a[3]` , and only broadcasts with other `ArrayPartition` s that have the same underlying sub-vector sizes, whereas `LazyArrays` ’ `Hcat` and `Vcat` will broadcast with just about anything afaict.

No, it does multiple index indexing like `a[3,5]`, which means the 3rd value in the 5th array (considering it like a matrix), and then `Array(a)` will “de-lazy” it into a real dense matrix.

---

<div class="post-metadata">

**Author:** ![kolia](https://avatars.discourse-cdn.com/v4/letter/k/c68b51/32.png) [@kolia](https://discourse.julialang.org/u/kolia)\
**Post date:** [January 19, 2019, 5:15am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/15 "2019-01-19T05:15:31Z")

</div>

Ah right, “multiple indexing” is not the term I should have used, `a[3, 5]` does indeed have the semantics you mention.

I meant non-scalar indexing as in `a[2:5]` or `a[[2,5,6]]`, non-scalar indexing currently errors with `ArrayPartition`. Fixed my post…

`ArrayPartition` and `Hcat`/`Vcat` implementations of getindex look similar under the hood, for both, `a[i]` loops over the sub-arrays, accumulating their lengths until you reach the sub-array containing index `i`. `ArrayPartition` implements multiple indexing with the semantics you mentioned, whereas `Vcat` only implements `a[i,j]` for 2 dim arrays, but not for 1d arrays.

Not sure why non-scalar indexing works for `Hcat`/`Vcat` and not for `ArrayPartition` upon cursory glance at the impls, or what it would take to add support for non-scalar indexing of `ArrayPartition`s.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [January 19, 2019, 6:19am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/16 "2019-01-19T06:19:17Z")

</div>

> [@kolia](#):
>
> I meant non-scalar indexing as in `a[2:5]` or `a[[2,5,6]]` , non-scalar indexing currently errors with `ArrayPartition` .

Interesting. I just never thought of doing that one. Could you open an issue?

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [January 19, 2019, 9:19am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/17 "2019-01-19T09:19:05Z")

</div>

I would always just write `reduce(hcat, v)` and expect the code to be optimised in the future unless the performance was critical right now. That’s IMHO the semantically correct way of expressing this operation.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [January 19, 2019, 9:26am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/18 "2019-01-19T09:26:57Z")

</div>

> [@mkborregaard](#):
>
> I would always just write `reduce(hcat, v)` and expect the code to be optimised

`reduce(hcat, v)` is optimized AFAIU.

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [January 19, 2019, 9:29am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/19 "2019-01-19T09:29:17Z")

</div>

Just saw that [https://github.com/JuliaLang/julia/pull/27188](https://github.com/JuliaLang/julia/pull/27188)  
So isn’t that the answer to the question?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [January 19, 2019, 9:34am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/20 "2019-01-19T09:34:41Z")

</div>

I guess it may be possible to optimize `Base._typed_vcat` (which implements it) further for some special cases (eg sparse arrays), but yes, #27188 takes care of this in a very nice way.

This also suggests the following general strategy: whenever one feels like coding a special-cased implementation for something like this, they might consider making the extra marginal effort of wrapping it up as a PR.

[Next page](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672.md?page=2)
