# Mapping with Flattening - Like a Kronecker Product

**URL:** <https://discourse.julialang.org/t/mapping-with-flattening-like-a-kronecker-product/59141>\
**Category:** New to Julia\
**Created:** [April 13, 2021, 1:26am UTC](https://discourse.julialang.org/t/mapping-with-flattening-like-a-kronecker-product/59141 "2021-04-13T01:26:22Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![GpuCoder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gpucoder/32/24511_2.png) [@GpuCoder](https://discourse.julialang.org/u/GpuCoder)\
**Post date:** [April 13, 2021, 1:26am UTC](https://discourse.julialang.org/t/mapping-with-flattening-like-a-kronecker-product/59141/1 "2021-04-13T01:26:22Z")

</div>

I want to do something like

```
A = map(x -> [x,2*x], transpose([1,2,3]))

```

which yields:

```
1×3 transpose(::Vector{LinearAlgebra.Transpose{Int64, Vector{Int64}}}) with eltype Vector{Int64}:
 [1, 2] [2, 4] [3, 6]

```

But I wanted

```
6-element Vector{Int64}:
 1
 2
 2
 4
 3
 6

```

I suspect there is some one-liner (or at least very simple) way of doing this. I understand how to write a function, perhaps called _KronLikeMap_ , that does this with 2 loops. But I can’t find anything useful in the manual.

The problem may be that I don’t know what searches to try.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [April 13, 2021, 3:50am UTC](https://discourse.julialang.org/t/mapping-with-flattening-like-a-kronecker-product/59141/2 "2021-04-13T03:50:58Z")

</div>

```julia
julia> A = reduce(vcat, map(x -> [x, 2*x], transpose([1, 2, 3])))
6-element Vector{Int64}:
 1
 2
 2
 4
 3
 6

```

---

<div class="post-metadata">

**Author:** ![GpuCoder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gpucoder/32/24511_2.png) [@GpuCoder](https://discourse.julialang.org/u/GpuCoder)\
**Post date:** [April 15, 2021, 3:21pm UTC](https://discourse.julialang.org/t/mapping-with-flattening-like-a-kronecker-product/59141/3 "2021-04-15T15:21:53Z")

</div>

Reduce-vcat and reduce-hcat solve a bunch of my other issues.

Thanks

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [April 15, 2021, 4:22pm UTC](https://discourse.julialang.org/t/mapping-with-flattening-like-a-kronecker-product/59141/4 "2021-04-15T16:22:44Z")

</div>

This is about four times faster on my machine, probably because it does less allocation. Maybe not as pretty.

```julia
myfill(a) = (v = Int[]; foreach(x -> push!(v, x, 2*x), a); v)

```

---

<div class="post-metadata">

**Author:** ![RobertGregg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robertgregg/32/22105_2.png) [@RobertGregg](https://discourse.julialang.org/u/RobertGregg)\
**Post date:** [April 15, 2021, 4:25pm UTC](https://discourse.julialang.org/t/mapping-with-flattening-like-a-kronecker-product/59141/5 "2021-04-15T16:25:41Z")

</div>

Raf’s response is awesome. If you wanted to be even slicker you could use:

```julia
mapreduce(x->[x,2x], vcat, [1,2,3])

```

Also you might not even need the transpose.

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [April 15, 2021, 4:34pm UTC](https://discourse.julialang.org/t/mapping-with-flattening-like-a-kronecker-product/59141/6 "2021-04-15T16:34:08Z")

</div>

I’m sure there is a scientific explanation for the following, but it is mysterious to me:

```julia
julia> const b = 1:1000;

julia> @btime mapreduce(x->(x,2x), vcat, b);
  764.033 μs (999 allocations: 7.78 MiB)

julia> @btime mapreduce(x->[x,2x], vcat, b);
  784.130 μs (1999 allocations: 7.87 MiB)

julia> @btime reduce(vcat, map(x -> (x, 2*x), b));
  792.793 μs (1000 allocations: 7.79 MiB)

julia> @btime reduce(vcat, map(x -> [x, 2*x], b));
  23.978 μs (1002 allocations: 117.44 KiB)

julia> @btime myfill(b);
  8.126 μs (11 allocations: 32.45 KiB)

```

---

<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:** [April 15, 2021, 8:37pm UTC](https://discourse.julialang.org/t/mapping-with-flattening-like-a-kronecker-product/59141/7 "2021-04-15T20:37:36Z")

</div>

> [@jlapeyre](#):
>
> ```julia
> julia> @btime mapreduce(x->[x,2x], vcat, b);
> 784.130 μs (1999 allocations: 7.87 MiB)
> 
> julia> @btime reduce(vcat, map(x -> (x, 2*x), b));
> 792.793 μs (1000 allocations: 7.79 MiB)
> 
> julia> @btime reduce(vcat, map(x -> [x, 2*x], b));
> 23.978 μs (1002 allocations: 117.44 KiB)
> 
> ```

`reduce(vcat, vector_of_arrays)` is fast because it has the manual performance overload:

> <https://github.com/JuliaLang/julia/blob/29d5158d27ddc3983ae2e373c4cd05569b9ead6c/base/abstractarray.jl#L1572-L1573>

Since it is easy to know the output element type in this case, I’d use `mapfoldl` + `append!`. It’s faster and more robust (i.e., works even if the input is empty):

```julia
julia> @btime reduce(vcat, map(x -> [x, 2*x], 1:1000));
  30.709 μs (1002 allocations: 117.44 KiB)

julia> @btime mapfoldl(x -> (x, 2x), append!, 1:1000; init = Int[]);
  9.830 μs (11 allocations: 32.45 KiB)

```

There’s probably no need to micro-optimize this. But, it is helpful to use the information of the output vector size. [`BangBang.collector`](https://juliafolds.github.io/BangBang.jl/dev/#BangBang.collector) is a composable tool for encoding this.:

```julia
julia> using BangBang

julia> @btime finish!(append!!(collector(Vector{Int}(undef, 2000), Val(true)), (y for x in 1:1000 for y in (x, 2x))));
  839.000 ns (1 allocation: 15.75 KiB)

```

---

<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:** [April 15, 2021, 8:42pm UTC](https://discourse.julialang.org/t/mapping-with-flattening-like-a-kronecker-product/59141/8 "2021-04-15T20:42:54Z")

</div>

This variant looks simple too:  
`vcat([[x,2x] for x in [1,2,3]]...)`
