# Permute NamedTuple based on names of another NamedTuple

**URL:** <https://discourse.julialang.org/t/permute-namedtuple-based-on-names-of-another-namedtuple/134088>\
**Category:** General Usage\
**Tags:** question, namedtuple\
**Created:** [November 24, 2025, 4:13pm UTC](https://discourse.julialang.org/t/permute-namedtuple-based-on-names-of-another-namedtuple/134088 "2025-11-24T16:13:35Z")\
**Posts on this page:** 4\
**Page:** 1

<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:** [November 24, 2025, 4:13pm UTC](https://discourse.julialang.org/t/permute-namedtuple-based-on-names-of-another-namedtuple/134088/1 "2025-11-24T16:13:35Z")

</div>

I would like to perform a calculation in **type space** : given a `NamedTuple{M,K}` type, permute its fields so that the names match a `NamedTuple{N}`. Example:

```julia
julia> p1(NamedTuple{(:a,:b)}, NamedTuple{(:b,:a),Tuple{Int,Float64}})
Tuple{Float64, Int64}

```

An example solution using generated functions, simplifications welcome:

```julia
@generated function p1(::Type{<:NamedTuple{N}},
                       ::Type{<:NamedTuple{M,K}}) where {N,M,K}
    # NOTE: solutions can assume that N is a permutation of M,
    # it is checked before
    _K = fieldtypes(K)
    S = map(N) do n
        i = findfirst(m -> m ≡ n, M)
        @assert i ≢ nothing
        _K[i]
    end
    :(Tuple{$(S...)})
end

```

---

<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:** [November 24, 2025, 5:44pm UTC](https://discourse.julialang.org/t/permute-namedtuple-based-on-names-of-another-namedtuple/134088/2 "2025-11-24T17:44:08Z")

</div>

```julia-auto
p2(::Type{<:NamedTuple{N}}, ::Type{T}) where {N, T<:NamedTuple} =
    Base.promote_op(nt -> values(nt[N]), T)

```

🙂  
Generally super convenient approach for transforming any value-based computation to a type-based computation. Comes at a slight cost of depending on the inference.

---

<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:** [November 24, 2025, 5:58pm UTC](https://discourse.julialang.org/t/permute-namedtuple-based-on-names-of-another-namedtuple/134088/3 "2025-11-24T17:58:06Z")

</div>

> [@aplavin](#):
>
> depending on the inference

Thanks, but just to clarify, I am looking for solutions without this shortcut.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [November 24, 2025, 7:51pm UTC](https://discourse.julialang.org/t/permute-namedtuple-based-on-names-of-another-namedtuple/134088/4 "2025-11-24T19:51:19Z")

</div>

> [@Tamas\_Papp](#):
>
> An example solution using generated functions, simplifications welcome:
> 
> ```julia-auto
> @generated function p1(::Type{<:NamedTuple{N}},
> ::Type{<:NamedTuple{M,K}}) where {N,M,K}
> # NOTE: solutions can assume that N is a permutation of M,
> # it is checked before
> _K = fieldtypes(K)
> S = map(N) do n
> i = findfirst(m -> m ≡ n, M)
> @assert i ≢ nothing
> _K[i]
> end
> :(Tuple{$(S...)})
> end
> 
> ```

Another option here would be to use `Base.@assume_effects` to write a non-generated function but still have it constant-fold based on the types:

```julia-auto
Base.@assume_effects :foldable function p1(::Type{<:NamedTuple{N}},
                                           ::Type{<:NamedTuple{M,K}}) where {N,M,K}
    # NOTE: solutions can assume that N is a permutation of M,
    # it is checked before
    _K = fieldtypes(K)
    S = map(N) do n
        i = findfirst(m -> m ≡ n, M)
        @assert i ≢ nothing
        _K[i]
    end
    Tuple{S...}
end

```

Not sure if this is really any nicer though.

Another option would be `Tuple` recursion:

```julia-auto
function p1(::Type{<:NamedTuple{N}},
            ::Type{<:NamedTuple{M,K}}) where {N,M,K}
    K′ = inner(N, M, fieldtypes(K))
    Tuple{K′...}
end

inner((head, tail...), M, K, K′=()) = let i = findfirst(==(head), M)
    @assert i ≢ nothing
    inner(tail, M, K, (K′..., K[i]))
end
inner(::Tuple{}, _, _, K′) = K′

```

The compiler appears to be good at optimizing this away (as expected for `Tuple` recursion):

```julia-auto
julia> @code_typed p1(@NamedTuple{a::Int, b::Float64}, @NamedTuple{b::ComplexF64, a::String})
CodeInfo(
1 ─ return Tuple{String, ComplexF64}
) => Type{Tuple{String, ComplexF64}}

```
