# 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:** 10\
**Page:** 3

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [October 15, 2019, 3:56am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/41 "2019-10-15T03:56:42Z")

</div>

> [@c42f](#):
>
> Yes, when I say I think it’s “interesting” I really mean it: I don’t know whether it’s good or bad overall

Got it. Yes, I’m very interested in this, too. How natural `op(xs...) == reduce(op, xs)` really is? If we implement optimization for `op(...f.(xs))` (or another syntax), are people going to use it? Is it less “scary” and more intuitive than `reduce`?

> [@c42f](#):
>
> If it could be made to compose really nicely with broadcast that might be fairly compelling.

Isn’t it enough to lower `op(...f.(xs))` to `reduce(op, broadcasted(f, xs))` so that broadcasting and reduction are fused? Can we do more than this?

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [October 15, 2019, 5:59am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/42 "2019-10-15T05:59:44Z")

</div>

> [@tkf](#):
>
> maybe it was decided that it was too much of a magic

Yes. Discussion is here: [stop being clever with reduction result types · Issue #20560 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/20560)

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [October 15, 2019, 6:21am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/43 "2019-10-15T06:21:26Z")

</div>

> [@tkf](#):
>
> Isn’t it enough to lower `op(...f.(xs))` to `reduce(op, broadcasted(f, xs))` so that broadcasting and reduction are fused? Can we do more than this?

Right: the reduction syntax acts as a barrier for broadcast and removes the call to `materialize`. I’m not sure anything else is required. We already discussed the `dims` keyword on the issue and it seemed clear that was an orthogonal problem.

---

<div class="post-metadata">

**Author:** ![sapo](https://avatars.discourse-cdn.com/v4/letter/s/ec9cab/32.png) [@sapo](https://discourse.julialang.org/u/sapo)\
**Post date:** [May 8, 2021, 8:38am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/44 "2021-05-08T08:38:06Z")

</div>

For me:

```julia
julia> a = fill(rand(1000), 1000)
julia> @time reduce(vcat, a');
  1.385112 seconds (4.99 k allocations: 3.729 GiB, 16.95% gc time)

julia> @time vcat(a'...);
  0.150527 seconds (361.89 k allocations: 31.163 MiB, 1.50% gc time, 69.42% compilation tim
e)

```

For `hcat`, simply don’t use the ellipsis

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [May 8, 2021, 10:50am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/45 "2021-05-08T10:50:35Z")

</div>

Instead of `reduce(vcat, a')` it seems faster to do `reduce(hcat,a)'`:

```julia
using BenchmarkTools
a = fill(rand(1000), 1000)
@btime vcat($a'...) # 3.374 ms (5017 allocations: 7.80 MiB)
@btime reduce(hcat,$a)' # 1.058 ms (2 allocations: 7.63 MiB)
@btime reduce(vcat, $a') # 1.298 s (4991 allocations: 3.73 GiB)

```

for the concatenation along the other direction, the following two seem to be equivalent:

```julia
@btime vcat($a...) # 1.046 ms (3 allocations: 7.64 MiB)
@btime reduce(vcat, $a) # 1.051 ms (3 allocations: 7.64 MiB)

```

---

<div class="post-metadata">

**Author:** ![xor0110](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xor0110/32/7926_2.png) [@xor0110](https://discourse.julialang.org/u/xor0110)\
**Post date:** [June 24, 2021, 8:08am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/46 "2021-06-24T08:08:11Z")

</div>

Julia defines the `identity` function if you would like to avoid the `x->x`.

---

<div class="post-metadata">

**Author:** ![adigitoleo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adigitoleo/32/27478_2.png) [@adigitoleo](https://discourse.julialang.org/u/adigitoleo)\
**Post date:** [July 24, 2021, 8:45am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/47 "2021-07-24T08:45:04Z")

</div>

I’m just curious if my understanding is correct: Do these discrepancies arise because of Julia’s column-major ordering for N-D arrays?

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [July 24, 2021, 9:25am UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/48 "2021-07-24T09:25:03Z")

</div>

No, it’s because there is an optimised version of `reduce(hcat, a)`, but `reduce(vcat, a')` goes to the fallback routine since `a'` is not an `AbstractVector`.

---

<div class="post-metadata">

**Author:** ![WinterTheJellyfish](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/winterthejellyfish/32/219499_2.png) [@WinterTheJellyfish](https://discourse.julialang.org/u/WinterTheJellyfish)\
**Post date:** [November 20, 2025, 11:11pm UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/49 "2025-11-20T23:11:58Z")

</div>

If X = [[1],[2,3,4],[5,6],[7]]  
Then try  
Y = [e[i] for e in X for i in (1:length(e))]

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/224680_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [November 20, 2025, 11:39pm UTC](https://discourse.julialang.org/t/very-best-way-to-concatenate-an-array-of-arrays/8672/50 "2025-11-20T23:39:00Z")

</div>

Hi @WinterTheJellyfish, welcome to the community!  
Please refrain from ressuscitating very old topics, this needlessly pings everyone who was involved in the conversation half a decade ago.  
By the way, the modern answer to this question is probably the `stack` function

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