# How to hcat a vector of vectors to produce a matrix with a specified eltype?

**URL:** <https://discourse.julialang.org/t/how-to-hcat-a-vector-of-vectors-to-produce-a-matrix-with-a-specified-eltype/84738>\
**Category:** General Usage\
**Tags:** array\
**Created:** [July 25, 2022, 7:34am UTC](https://discourse.julialang.org/t/how-to-hcat-a-vector-of-vectors-to-produce-a-matrix-with-a-specified-eltype/84738 "2022-07-25T07:34:39Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [July 25, 2022, 7:34am UTC](https://discourse.julialang.org/t/how-to-hcat-a-vector-of-vectors-to-produce-a-matrix-with-a-specified-eltype/84738/1 "2022-07-25T07:34:39Z")

</div>

What I want is basically an equivalent of

```julia
julia> A = [1:4, 5:8]
2-element Vector{UnitRange{Int64}}:
 1:4
 5:8

julia> Base.typed_hcat(Float64, A...)
4×2 Matrix{Float64}:
 1.0 5.0
 2.0 6.0
 3.0 7.0
 4.0 8.0

```

except without splatting and calling internal functions. I can do this as

```julia
julia> convert(Array{Float64}, reduce(hcat, A))
4×2 Matrix{Float64}:
 1.0 5.0
 2.0 6.0
 3.0 7.0
 4.0 8.0

```

however, this allocates an intermediate array, which I’m trying to avoid. Ideally I’ll want to use public `Base` functions to evaluate the result.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [July 25, 2022, 9:34am UTC](https://discourse.julialang.org/t/how-to-hcat-a-vector-of-vectors-to-produce-a-matrix-with-a-specified-eltype/84738/2 "2022-07-25T09:34:59Z")

</div>

try to see if combinedimsview function of SplitApplyCombine.jl is right for you

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [July 25, 2022, 10:49am UTC](https://discourse.julialang.org/t/how-to-hcat-a-vector-of-vectors-to-produce-a-matrix-with-a-specified-eltype/84738/3 "2022-07-25T10:49:31Z")

</div>

Does this allow passing the `eltype` as a parameter? From the docstrings it seems that the eltype of the output is automatically inferred

One way is to use the internal type directly

```julia
julia> CombineDimsArray{Float64, 2, 1, typeof(A)}(A, (2,))
4×2 CombineDimsArray{Float64, 2, 1, Vector{UnitRange{Int64}}}:
 1 5
 2 6
 3 7
 4 8

```

but this defeats the purpose.

---

<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:** [July 25, 2022, 10:56am UTC](https://discourse.julialang.org/t/how-to-hcat-a-vector-of-vectors-to-produce-a-matrix-with-a-specified-eltype/84738/4 "2022-07-25T10:56:36Z")

</div>

Not a solution but for completeness `Float64[A...;;]` is public Base only and short, but splatting and not particularly efficient.

---

<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:** [July 25, 2022, 12:04pm UTC](https://discourse.julialang.org/t/how-to-hcat-a-vector-of-vectors-to-produce-a-matrix-with-a-specified-eltype/84738/5 "2022-07-25T12:04:01Z")

</div>

You can use the `init` argument to `reduce`:

```julia
julia> reduce(hcat, A, init=Array{Float64}(undef,4,0))
4×2 Matrix{Float64}:
 1.0 5.0
 2.0 6.0
 3.0 7.0
 4.0 8.0

```

(Unfortunately `reduce` with `hcat` is currently [unoptimized in the case with an `init` argument](https://github.com/JuliaLang/julia/issues/31137#issuecomment-1184517298), but this could be easily fixed if someone wanted to work on a PR.)

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [July 25, 2022, 9:16pm UTC](https://discourse.julialang.org/t/how-to-hcat-a-vector-of-vectors-to-produce-a-matrix-with-a-specified-eltype/84738/6 "2022-07-25T21:16:22Z")

</div>

some functions compared

```julia
julia> using BenchmarkTools

julia> using SplitApplyCombine

julia> function recombdims(A) 
           od=last(eachindex(A))
           id=last(eachindex(first(A)))
           out=similar(A,Float64, id,od)
           for j in eachindex(A)
               for i in eachindex(first(A))
                   out[i,j]=A[j][i]
               end
           end
           out
       end
recombdims (generic function with 1 method)

julia> function hcat_typ1(A)
           od=first(size(A))
           id=first(size(first(A)))
           out=similar(A[1],Float64,id,od)
           for i in eachindex(A)
               copyto!(out,id*(i-1)+1, A[i], 1)
           end
           out
       end
hcat_typ1 (generic function with 1 method)

julia> A=[rand(1:10, 7) for _ in 1:10^4];

julia> @btime hcat_typ1($A)
  89.900 μs (2 allocations: 546.92 KiB)
7×10000 Matrix{Float64}:
  3.0 8.0 5.0 1.0 2.0 5.0 5.0 … 9.0 3.0 3.0 10.0 6.0 10.0
 10.0 1.0 4.0 9.0 7.0 9.0 10.0 5.0 10.0 3.0 9.0 3.0 5.0
  4.0 5.0 8.0 1.0 4.0 7.0 3.0 5.0 2.0 8.0 3.0 4.0 7.0
  2.0 4.0 6.0 6.0 8.0 8.0 9.0 2.0 5.0 10.0 3.0 7.0 4.0
  9.0 6.0 9.0 9.0 3.0 4.0 3.0 8.0 5.0 3.0 4.0 4.0 4.0
  8.0 2.0 6.0 8.0 2.0 10.0 2.0 … 10.0 9.0 4.0 7.0 8.0 2.0
  6.0 1.0 10.0 1.0 6.0 4.0 8.0 9.0 10.0 1.0 8.0 8.0 4.0      

julia> @btime recombdims($A)
  175.400 μs (2 allocations: 546.92 KiB)
7×10000 Matrix{Float64}:
  3.0 8.0 5.0 1.0 2.0 5.0 5.0 … 9.0 3.0 3.0 10.0 6.0 10.0
 10.0 1.0 4.0 9.0 7.0 9.0 10.0 5.0 10.0 3.0 9.0 3.0 5.0
  4.0 5.0 8.0 1.0 4.0 7.0 3.0 5.0 2.0 8.0 3.0 4.0 7.0
  2.0 4.0 6.0 6.0 8.0 8.0 9.0 2.0 5.0 10.0 3.0 7.0 4.0
  9.0 6.0 9.0 9.0 3.0 4.0 3.0 8.0 5.0 3.0 4.0 4.0 4.0
  8.0 2.0 6.0 8.0 2.0 10.0 2.0 … 10.0 9.0 4.0 7.0 8.0 2.0
  6.0 1.0 10.0 1.0 6.0 4.0 8.0 9.0 10.0 1.0 8.0 8.0 4.0

julia> @btime convert(Array{Float64}, reduce(hcat, $A))
  151.900 μs (4 allocations: 1.07 MiB)
7×10000 Matrix{Float64}:
  3.0 8.0 5.0 1.0 2.0 5.0 5.0 … 9.0 3.0 3.0 10.0 6.0 10.0
 10.0 1.0 4.0 9.0 7.0 9.0 10.0 5.0 10.0 3.0 9.0 3.0 5.0
  4.0 5.0 8.0 1.0 4.0 7.0 3.0 5.0 2.0 8.0 3.0 4.0 7.0
  2.0 4.0 6.0 6.0 8.0 8.0 9.0 2.0 5.0 10.0 3.0 7.0 4.0
  9.0 6.0 9.0 9.0 3.0 4.0 3.0 8.0 5.0 3.0 4.0 4.0 4.0
  8.0 2.0 6.0 8.0 2.0 10.0 2.0 … 10.0 9.0 4.0 7.0 8.0 2.0
  6.0 1.0 10.0 1.0 6.0 4.0 8.0 9.0 10.0 1.0 8.0 8.0 4.0

julia> @btime convert(Array{Float64},combinedims($A))
  208.600 μs (4 allocations: 1.07 MiB)
7×10000 Matrix{Float64}:
  3.0 8.0 5.0 1.0 2.0 5.0 5.0 … 9.0 3.0 3.0 10.0 6.0 10.0
 10.0 1.0 4.0 9.0 7.0 9.0 10.0 5.0 10.0 3.0 9.0 3.0 5.0
  4.0 5.0 8.0 1.0 4.0 7.0 3.0 5.0 2.0 8.0 3.0 4.0 7.0
  2.0 4.0 6.0 6.0 8.0 8.0 9.0 2.0 5.0 10.0 3.0 7.0 4.0
  9.0 6.0 9.0 9.0 3.0 4.0 3.0 8.0 5.0 3.0 4.0 4.0 4.0
  8.0 2.0 6.0 8.0 2.0 10.0 2.0 … 10.0 9.0 4.0 7.0 8.0 2.0
  6.0 1.0 10.0 1.0 6.0 4.0 8.0 9.0 10.0 1.0 8.0 8.0 4.0

julia> @btime reduce(hcat, $A, init=Array{Float64}(undef,7,0))
  351.056 ms (19709 allocations: 2.61 GiB)
7×10000 Matrix{Float64}:
  3.0 8.0 5.0 1.0 2.0 5.0 5.0 … 9.0 3.0 3.0 10.0 6.0 10.0
 10.0 1.0 4.0 9.0 7.0 9.0 10.0 5.0 10.0 3.0 9.0 3.0 5.0
  4.0 5.0 8.0 1.0 4.0 7.0 3.0 5.0 2.0 8.0 3.0 4.0 7.0
  2.0 4.0 6.0 6.0 8.0 8.0 9.0 2.0 5.0 10.0 3.0 7.0 4.0
  9.0 6.0 9.0 9.0 3.0 4.0 3.0 8.0 5.0 3.0 4.0 4.0 4.0
  8.0 2.0 6.0 8.0 2.0 10.0 2.0 … 10.0 9.0 4.0 7.0 8.0 2.0
  6.0 1.0 10.0 1.0 6.0 4.0 8.0 9.0 10.0 1.0 8.0 8.0 4.0

```

---

<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:** [July 25, 2022, 10:14pm UTC](https://discourse.julialang.org/t/how-to-hcat-a-vector-of-vectors-to-produce-a-matrix-with-a-specified-eltype/84738/7 "2022-07-25T22:14:41Z")

</div>

> [@rocco\_sprmnt21](#):
>
> `last(eachindex(A))`

See `lastindex` and `firstindex` functions.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [July 26, 2022, 7:08am UTC](https://discourse.julialang.org/t/how-to-hcat-a-vector-of-vectors-to-produce-a-matrix-with-a-specified-eltype/84738/8 "2022-07-26T07:08:01Z")

</div>

using these functions instead of my crude combination improves performance.  
I also propose a change to hcat\_typ1 which seems to do slightly better

```julia
julia> function recombdims(A) 
                   A1=first(A)
                  od=lastindex(A)
                  id=lastindex(A1)
                  out=similar(A,Float64, id,od)
                  for j in eachindex(A)
                      for i in eachindex(A1)
                          out[i,j]=A[j][i]
                      end
                  end
                  out
              end
recombdims (generic function with 1 method)

julia> @btime recombdims($A);
  74.500 μs (2 allocations: 546.92 KiB)

julia> function hcat_typ2(A)
                  od=first(size(A))
                  id=first(size(first(A)))
                  out=similar(A[1],Float64,id,od)
                  pos=1
                  for i in eachindex(A)
                      copyto!(out,pos, A[i], 1, id)
                      pos+=id
                  end
                  out
       end
hcat_typ2 (generic function with 1 method)

julia> @btime hcat_typ2($A)
  69.900 μs (2 allocations: 546.92 KiB)

```

I can’t understand why the reduce with `init =` is so much worse than the one without it.  
I could not take the test (it did not finish after several minutes and I had to restart the session) with A such that `size (A) = (10 ^ 7,)`

```julia
julia> @btime convert(Array{Float64}, reduce(hcat, $A))
  153.200 μs (4 allocations: 1.07 MiB)

julia> @btime reduce(hcat, $A, init=Array{Float64}(undef,7,0))
  431.882 ms (19709 allocations: 2.61 GiB)

```

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [July 26, 2022, 8:13am UTC](https://discourse.julialang.org/t/how-to-hcat-a-vector-of-vectors-to-produce-a-matrix-with-a-specified-eltype/84738/9 "2022-07-26T08:13:34Z")

</div>

This should work, and is both intuitive and efficient:

```julia
using SplitApplyCombine

# get a materialized array without intermediate allocations:
map(Float64, combinedimsview(A))

# get a view of the original array - basically free, you pay when accessing it:
mapview(Float64, combinedimsview(A))

```

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [July 26, 2022, 8:50am UTC](https://discourse.julialang.org/t/how-to-hcat-a-vector-of-vectors-to-produce-a-matrix-with-a-specified-eltype/84738/10 "2022-07-26T08:50:55Z")

</div>

```julia
julia> map(Float64, combinedimsview(A))
4×2 Matrix{Float64}:
 1.0 5.0
 2.0 6.0
 3.0 7.0
 4.0 8.0

julia> map(Real, combinedimsview(A))
4×2 Matrix{Int64}:
 1 5
 2 6
 3 7
 4 8

julia> convert(Array{Real}, combinedimsview(A))
4×2 Matrix{Real}:
 1 5
 2 6
 3 7
 4 8

julia> convert(Array{Float64}, combinedimsview(A))
4×2 Matrix{Float64}:
 1.0 5.0
 2.0 6.0
 3.0 7.0
 4.0 8.0

```

`convert` is better than `map` here, as it preserves the exact `eltype` even if it is an abstract type.
