# \`unsqueeze\` or \`insertdims\` not part of Base

**URL:** <https://discourse.julialang.org/t/unsqueeze-or-insertdims-not-part-of-base/82508>\
**Category:** General Usage\
**Created:** [June 9, 2022, 3:26pm UTC](https://discourse.julialang.org/t/unsqueeze-or-insertdims-not-part-of-base/82508 "2022-06-09T15:26:59Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)\
**Post date:** [June 9, 2022, 3:26pm UTC](https://discourse.julialang.org/t/unsqueeze-or-insertdims-not-part-of-base/82508/1 "2022-06-09T15:26:59Z")

</div>

Hi!

in Base we have `dropdims` which effectively calls [`reshape`](https://github.com/JuliaLang/julia/blob/bd26069cee94bda2b7dec498a6bf92fb2aff76d7/base/abstractarraymath.jl#L92).  
Today, I was confused that we don’t have `insertdims` being the inverse to the former.

There is already one implementation in [MLUtils.jl](https://github.com/JuliaML/MLUtils.jl/blob/46e9f2cb2129dbcb259185a2509154bbe5b0afe9/src/utils.jl#L36) for a single dim. However, it should be possible to generalize that to tuple of dims.

Is there a reason we don’t have that in Base?

Best,

Felix

---

<div class="post-metadata">

**Author:** ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)\
**Post date:** [June 13, 2022, 10:59am UTC](https://discourse.julialang.org/t/unsqueeze-or-insertdims-not-part-of-base/82508/2 "2022-06-13T10:59:02Z")

</div>

I tried to implement `insertdims` similarly to `dropdims`.

Is that something we should try to add to Base?

```julia
insertdims(A; dims) = _insertdims(A, dims)
function _insertdims(A::AbstractArray{T, N}, dims::Tuple{Vararg{Int64, M}}) where {T, N, M}
    for i in eachindex(dims)
        for j = 1:i-1
            dims[j] == dims[i] && throw(ArgumentError("inserted dims must be unique"))
        end
    end 

    # sorted list of dims
    new_dims = _sortedmerge(ntuple(identity, Val(N)), dims)
    for i in 2:length(new_dims)
        new_dims[i-1] == new_dims[i] || new_dims[i-1] + 1 == new_dims[i] ||
            throw(ArgumentError("inserted dims and existing dims must be contiguos"))
    end

    # n is the amount of the dims already inserted
    ax_n = Base._foldoneto(((ds, n), d) -> d in dims ? ((ds..., 1), n+1) : ((ds..., axes(A,d - n)), n), 
                         ((), 0), Val(ndims(A) + length(dims)))
    # we need only the new shape and not n
    reshape(A, ax_n[1])::AbstractArray{T, N + M}
end
_insertdims(A::AbstractArray, dim::Integer) = _insertdims(A, (Int(dim),))

_sortedmerge(::Tuple{}, ::Tuple{}) = ()
_sortedmerge(::Tuple{}, s::Tuple) = s 
_sortedmerge(t::Tuple, s::Tuple{}) = t 
_sortedmerge(t::Tuple, s::Tuple) = (first(s) < first(t) ? (first(s), _sortedmerge(t, Base.tail(s))...) 
                                                        : (first(t), _sortedmerge(Base.tail(t), s)...))

```
