# How to create permutation of named tuple values

**URL:** <https://discourse.julialang.org/t/how-to-create-permutation-of-named-tuple-values/119821>\
**Category:** General Usage\
**Created:** [September 24, 2024, 5:25pm UTC](https://discourse.julialang.org/t/how-to-create-permutation-of-named-tuple-values/119821 "2024-09-24T17:25:49Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)\
**Post date:** [September 24, 2024, 5:25pm UTC](https://discourse.julialang.org/t/how-to-create-permutation-of-named-tuple-values/119821/1 "2024-09-24T17:25:49Z")

</div>

# how can I write a generic function to generate permutations of arbitrary named tuple values

# this is what I currently do

```julia-auto
    catagory0 = [1,3,4]
    letter0 = ["a", "b", "c"]
    score0 = [1.1, 4.]
    thing0 = ["hat", "cat"]

    nt = NamedTuple[]
    for catagory in catagory0
        for letter in letter0
            for score in score0
                for thing in thing0
                    push!(nt, (;catagory, letter, score, thing))
                end
            end
        end
    end

    julia> nt
    36-element Vector{NamedTuple}:
    (catagory = 1, letter = "a", score = 1.1, thing = "hat")
    (catagory = 1, letter = "a", score = 1.1, thing = "cat")
    (catagory = 1, letter = "a", score = 4.0, thing = "hat")
    (catagory = 1, letter = "a", score = 4.0, thing = "cat")
    (catagory = 1, letter = "b", score = 1.1, thing = "hat")
    ⋮
    (catagory = 4, letter = "c", score = 1.1, thing = "hat")
    (catagory = 4, letter = "c", score = 1.1, thing = "cat")
    (catagory = 4, letter = "c", score = 4.0, thing = "hat")
    (catagory = 4, letter = "c", score = 4.0, thing = "cat")

```

# I would like to write a generic function `ntpermutations` that does the above but accepts any named tuple of values

```julia-auto
  nt_in = (;catagory = [1, 3, 4], letter = ["a", "b", "c"], score = [1.1, 4.0], thing = ["hat", "cat"])
  nt = ntpermutations(nt_in)

```

# where in this case nt == nt from first example

---

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [September 24, 2024, 6:06pm UTC](https://discourse.julialang.org/t/how-to-create-permutation-of-named-tuple-values/119821/2 "2024-09-24T18:06:46Z")

</div>

You could use

```julia
ntpermutations(nt_in) = [NamedTuple{keys(nt_in)}(reverse(t)) for t in Iterators.product(reverse(nt_in)...)] |> vec

```

```julia-repl
julia> nt_in = (; category = [1, 3, 4], letter = ["a", "b", "c"], score = [1.1, 4.0], thing = ["hat", "cat"])
(category = [1, 3, 4], letter = ["a", "b", "c"], score = [1.1, 4.0], thing = ["hat", "cat"])

julia> nt = ntpermutations(nt_in)
36-element Vector{@NamedTuple{category::Int64, letter::String, score::Float64, thing::String}}:
 (category = 1, letter = "a", score = 1.1, thing = "hat")
 (category = 1, letter = "a", score = 1.1, thing = "cat")
 (category = 1, letter = "a", score = 4.0, thing = "hat")
 (category = 1, letter = "a", score = 4.0, thing = "cat")
 (category = 1, letter = "b", score = 1.1, thing = "hat")
 (category = 1, letter = "b", score = 1.1, thing = "cat")
 (category = 1, letter = "b", score = 4.0, thing = "hat")
 (category = 1, letter = "b", score = 4.0, thing = "cat")
 (category = 1, letter = "c", score = 1.1, thing = "hat")
 (category = 1, letter = "c", score = 1.1, thing = "cat")
 (category = 1, letter = "c", score = 4.0, thing = "hat")
 (category = 1, letter = "c", score = 4.0, thing = "cat")
 (category = 3, letter = "a", score = 1.1, thing = "hat")
 ⋮
 (category = 4, letter = "a", score = 1.1, thing = "hat")
 (category = 4, letter = "a", score = 1.1, thing = "cat")
 (category = 4, letter = "a", score = 4.0, thing = "hat")
 (category = 4, letter = "a", score = 4.0, thing = "cat")
 (category = 4, letter = "b", score = 1.1, thing = "hat")
 (category = 4, letter = "b", score = 1.1, thing = "cat")
 (category = 4, letter = "b", score = 4.0, thing = "hat")
 (category = 4, letter = "b", score = 4.0, thing = "cat")
 (category = 4, letter = "c", score = 1.1, thing = "hat")
 (category = 4, letter = "c", score = 1.1, thing = "cat")
 (category = 4, letter = "c", score = 4.0, thing = "hat")
 (category = 4, letter = "c", score = 4.0, thing = "cat")

```

If you don’t care about the order, you can remove the `reverse`s.

## Explanation

- `Iterators.product(reverse(nt_in)...)` creates an iterator containing all possible tuples whose entries are taken from the elements in the fields of `nt_in`. The first axis in `Iterators.product` will cycle the fastest. Thanks to the `reverse`, `nt_in`’s first field (category) is put at the back and hence changes slowest.
- `NamedTuple{keys(nt_in)}(reverse(t))` takes such a tuple `t` and converts it in a `NamedTuple` with the same names as `nt_in`. We have to undo the reverse from before.
- `|> vec`: `Iterators.product` produces an `n`-dimensional structure, where `n = length(nt_in)`. The list comprehension then creates an `Array{@NamedTuple{...}, n}`, which we flatten to a `Vector`.

---

<div class="post-metadata">

**Author:** ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)\
**Post date:** [September 24, 2024, 6:17pm UTC](https://discourse.julialang.org/t/how-to-create-permutation-of-named-tuple-values/119821/3 "2024-09-24T18:17:12Z")

</div>

in a single line nonetheless! Works like a charm.
