You could use
ntpermutations(nt_in) = [NamedTuple{keys(nt_in)}(reverse(t)) for t in Iterators.product(reverse(nt_in)...)] |> vec
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 ofnt_in
. The first axis inIterators.product
will cycle the fastest. Thanks to thereverse
,nt_in
’s first field (category) is put at the back and hence changes slowest.NamedTuple{keys(nt_in)}(reverse(t))
takes such a tuplet
and converts it in aNamedTuple
with the same names asnt_in
. We have to undo the reverse from before.|> vec
:Iterators.product
produces ann
-dimensional structure, wheren = length(nt_in)
. The list comprehension then creates anArray{@NamedTuple{...}, n}
, which we flatten to aVector
.