# Product iterator with NamedTuples

**URL:** <https://discourse.julialang.org/t/product-iterator-with-namedtuples/83319>\
**Category:** General Usage\
**Tags:** question, namedtuple, iterators\
**Created:** [June 24, 2022, 4:54pm UTC](https://discourse.julialang.org/t/product-iterator-with-namedtuples/83319 "2022-06-24T16:54:56Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [June 24, 2022, 4:54pm UTC](https://discourse.julialang.org/t/product-iterator-with-namedtuples/83319/1 "2022-06-24T16:54:56Z")

</div>

Hi all,

I was wondering whether it is possible to create a product iterator consisting of NamedTuples. The product iterator generates tuples like so:

```julia
Base.product(1:3,4:5) |> collect
3×2 Matrix{Tuple{Int64, Int64}}:
 (1, 4) (1, 5)
 (2, 4) (2, 5)
 (3, 4) (3, 5)

```

What I would like to do is associate each element with a keyword, such as:

```julia
 (a=1, b=4) (a=1, b=5)
 (a=2, b=4) (a=2, b=5)
 (a=3, b=4) (a=3, b=5)

```

Is this possible?

---

<div class="post-metadata">

**Author:** ![zweiglimmergneis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zweiglimmergneis/32/7892_2.png) [@zweiglimmergneis](https://discourse.julialang.org/u/zweiglimmergneis)\
**Post date:** [June 24, 2022, 5:50pm UTC](https://discourse.julialang.org/t/product-iterator-with-namedtuples/83319/2 "2022-06-24T17:50:28Z")

</div>

Is this generic enough?

```julia
julia> abTuple(t) = (; zip((:a, :b), t)...)
abTuple (generic function with 1 method)

julia> Base.product(1:3,4:5) .|> abTuple
3×2 Matrix{NamedTuple{(:a, :b), Tuple{Int64, Int64}}}:
 (a = 1, b = 4) (a = 1, b = 5)
 (a = 2, b = 4) (a = 2, b = 5)
 (a = 3, b = 4) (a = 3, b = 5)

```

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [June 24, 2022, 6:39pm UTC](https://discourse.julialang.org/t/product-iterator-with-namedtuples/83319/3 "2022-06-24T18:39:19Z")

</div>

> [@zweiglimmergneis](#):
>
> `Base.product(1:3,4:5) .|> abTuple`

Yes. Thank you. This will work for my use case. I suppose one way to make it more generic is to create a custom iterator.

---

<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:** [June 25, 2022, 4:24am UTC](https://discourse.julialang.org/t/product-iterator-with-namedtuples/83319/4 "2022-06-25T04:24:24Z")

</div>

Another way might be to broadcast the constructor, as

```julia
julia> it = Base.product(1:3, 4:5);

julia> @NamedTuple{a::Int, b::Int}.(it)
3×2 Matrix{NamedTuple{(:a, :b), Tuple{Int64, Int64}}}:
 (a = 1, b = 4) (a = 1, b = 5)
 (a = 2, b = 4) (a = 2, b = 5)
 (a = 3, b = 4) (a = 3, b = 5)

```

A lazy version might be

```julia
julia> g = (@NamedTuple{a::Int, b::Int}(x) for x in it)

julia> collect(g)
3×2 Matrix{NamedTuple{(:a, :b), Tuple{Int64, Int64}}}:
 (a = 1, b = 4) (a = 1, b = 5)
 (a = 2, b = 4) (a = 2, b = 5)
 (a = 3, b = 4) (a = 3, b = 5)

```

---

<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:** [June 25, 2022, 5:23pm UTC](https://discourse.julialang.org/t/product-iterator-with-namedtuples/83319/5 "2022-06-25T17:23:46Z")

</div>

For something more than an iterator, see _(my)_ [RectiGrids.jl](https://gitlab.com/aplavin/RectiGrids.jl) package:

```julia
julia> using RectiGrids

# create a grid with named dimensions:
julia> G = grid(a=1:3, b=4:5)
2-dimensional KeyedArray(NamedDimsArray(...)) with keys:
↓ a ∈ 3-element UnitRange{Int64}
→ b ∈ 2-element UnitRange{Int64}
And data, 3×2 RectiGrids.RectiGridArr{(:a, :b), NamedTuple{(:a, :b), Tuple{Int64, Int64}}, 2, Tuple{Nothing, Nothing}, Tuple{UnitRange{Int64}, UnitRange{Int64}}}:
      (4) (5)
 (1) (a = 1, b = 4) (a = 1, b = 5)
 (2) (a = 2, b = 4) (a = 2, b = 5)
 (3) (a = 3, b = 4) (a = 3, b = 5)

# it behaves as an array, with NamedTuple elements:
julia> G[1, 2]
(a = 1, b = 5)

# even more, a grid is a KeyedArray and can use any of KeyedArray selectors
# this still doesn't materialize the whole grid:
julia> G(a = >(1)) # only keep values with a > 1
2-dimensional KeyedArray(NamedDimsArray(...)) with keys:
↓ a ∈ 2-element UnitRange{Int64}
→ b ∈ 2-element UnitRange{Int64}
And data, 2×2 view(::RectiGrids.RectiGridArr{(:a, :b), NamedTuple{(:a, :b), Tuple{Int64, Int64}}, 2, Tuple{Nothing, Nothing}, Tuple{UnitRange{Int64}, UnitRange{Int64}}}, 2:3, :) with eltype NamedTuple{(:a, :b), Tuple{Int64, Int64}}:
      (4) (5)
 (2) (a = 2, b = 4) (a = 2, b = 5)
 (3) (a = 3, b = 4) (a = 3, b = 5)

# applying a function over the grid keeps the keyed indices (a and b):
julia> map(x -> x.a^2 + x.b, G)
2-dimensional KeyedArray(NamedDimsArray(...)) with keys:
↓ a ∈ 3-element UnitRange{Int64}
→ b ∈ 2-element UnitRange{Int64}
And data, 3×2 Matrix{Int64}:
      (4) (5)
 (1) 5 6
 (2) 8 9
 (3) 13 14

```

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [June 25, 2022, 5:42pm UTC](https://discourse.julialang.org/t/product-iterator-with-namedtuples/83319/6 "2022-06-25T17:42:29Z")

</div>

Awesome. Thank you for all of the ideas!
