How to get something like (0:7)^4
, but for a custom iterator, and for an arbitrary positive integer exponent? The result should be similar to Iterators.product(0:7, 0:7, 0:7, 0:7)
, but type stable.
julia> it = (i for i in rand(1:10, 20))
Base.Generator{Vector{Int64}, typeof(identity)}(identity, [3, 2, 8, 10, 1, 7, 4, 6, 7, 2, 4, 1, 6, 8, 9, 7, 4, 1, 10, 2])
julia> map(x -> x^5, it)
20-element Vector{Int64}:
243
32
32768
100000
1
# ...
?
No, I want something like this, but type stable:
iter_pow(it, n) = Iterators.product([it for i in 1:n]...)
1 Like
Interesting question. I doubt this is the best answer, but:
julia> A × B = (Iterators.Flatten((a, b)) for a in A for b in B)
× (generic function with 1 method)
julia> reduce(×, 0:4 for _ in 1:3)
Base.Iterators.Flatten{Base.Generator{Base.Iterators.Flatten{Base.Generator{UnitRange{Int64}, var"#52#53"{UnitRange{Int64}}}}, var"#52#53"{UnitRange{Int64}}}}(Base.Generator{Base.Iterators.Flatten{Base.Generator{UnitRange{Int64}, var"#52#53"{UnitRange{Int64}}}}, var"#52#53"{UnitRange{Int64}}}(var"#52#53"{UnitRange{Int64}}(0:4), Base.Iterators.Flatten{Base.Generator{UnitRange{Int64}, var"#52#53"{UnitRange{Int64}}}}(Base.Generator{UnitRange{Int64}, var"#52#53"{UnitRange{Int64}}}(var"#52#53"{UnitRange{Int64}}(0:4), 0:4))))
julia> collect(collect(i) for i in ans)
125-element Vector{Vector{Int64}}:
[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
# ...
where the ×
operator defined above might be the rare legitimate use case for defining infix operators as discussed in this other thread from today: Does anybody use the syntax `a <operator> b = ...` to define new methods for operators? - #8 by dylanxyz
This could be a useful feature in Combinatorics.jl.
1 Like
Oh, how about this?
julia> Iterators.product((0:7 for _ in 1:4)...)
Base.Iterators.ProductIterator{NTuple{4, UnitRange{Int64}}}((0:7, 0:7, 0:7, 0:7))
julia> collect(ans)
8×8×8×8 Array{NTuple{4, Int64}, 4}:
[:, :, 1, 1] =
(0, 0, 0, 0) (0, 1, 0, 0) (0, 2, 0, 0) (0, 3, 0, 0) (0, 4, 0, 0) (0, 5, 0, 0) (0, 6, 0, 0) (0, 7, 0, 0)
(1, 0, 0, 0) (1, 1, 0, 0) (1, 2, 0, 0) (1, 3, 0, 0) (1, 4, 0, 0) (1, 5, 0, 0) (1, 6, 0, 0) (1, 7, 0, 0)
(2, 0, 0, 0) (2, 1, 0, 0) (2, 2, 0, 0) (2, 3, 0, 0) (2, 4, 0, 0) (2, 5, 0, 0) (2, 6, 0, 0) (2, 7, 0, 0)
(3, 0, 0, 0) (3, 1, 0, 0) (3, 2, 0, 0) (3, 3, 0, 0) (3, 4, 0, 0) (3, 5, 0, 0) (3, 6, 0, 0) (3, 7, 0, 0)
(4, 0, 0, 0) (4, 1, 0, 0) (4, 2, 0, 0) (4, 3, 0, 0) (4, 4, 0, 0) (4, 5, 0, 0) (4, 6, 0, 0) (4, 7, 0, 0)
(5, 0, 0, 0) (5, 1, 0, 0) (5, 2, 0, 0) (5, 3, 0, 0) (5, 4, 0, 0) (5, 5, 0, 0) (5, 6, 0, 0) (5, 7, 0, 0)
(6, 0, 0, 0) (6, 1, 0, 0) (6, 2, 0, 0) (6, 3, 0, 0) (6, 4, 0, 0) (6, 5, 0, 0) (6, 6, 0, 0) (6, 7, 0, 0)
(7, 0, 0, 0) (7, 1, 0, 0) (7, 2, 0, 0) (7, 3, 0, 0) (7, 4, 0, 0) (7, 5, 0, 0) (7, 6, 0, 0) (7, 7, 0, 0)
...
1 Like
I think I’ll use this in the end:
iter_pow(it::It, ::Val{n}) where {It <: Any, n} =
Iterators.product(
ntuple(
let it = it
i -> it
end,
Val(n))...)
2 Likes