ccarnauba
ccarnauba

Reputation: 23

Using Iterators.product on a variable number of lists

I'm trying to make a function that use Iterators.product() on a variable number of arrays. This is my code:

function make_feature_space(dictionary, k)
    dict_chars = collect(dictionary)
    #Change bottom line
    dict_product = collect(Iterators.product(dict_chars))
    return dict_product
end

The behavior I'd like would be something along the lines of calling make_feature_space(dictionary, 3) would return Iterators.product(dict_chars, dict_chars, dict_chars), but calling make_feature_space(dictionary, 2) would get Iterators.product(dict_chars, dict_chars). Thanks!!

Upvotes: 2

Views: 354

Answers (1)

Cameron Bieganek
Cameron Bieganek

Reputation: 7674

Here's a solution that uses Iterators.repeated and splatting:

using Base.Iterators

make_feature_space(x, n) = product(repeated(x, n)...)

Here it is in action:

julia> x = 1:2;

julia> make_feature_space(x, 2) |> collect
2×2 Array{Tuple{Int64,Int64},2}:
 (1, 1)  (1, 2)
 (2, 1)  (2, 2)

julia> make_feature_space(x, 3) |> collect
2×2×2 Array{Tuple{Int64,Int64,Int64},3}:
[:, :, 1] =
 (1, 1, 1)  (1, 2, 1)
 (2, 1, 1)  (2, 2, 1)

[:, :, 2] =
 (1, 1, 2)  (1, 2, 2)
 (2, 1, 2)  (2, 2, 2)

Note that this implementation can use any iterator in the first argument of make_feature_space. Further note that a dictionary is an iterator of pairs, so you can do this:

julia> d = Dict(:a => 1, :b => 2)
Dict{Symbol,Int64} with 2 entries:
  :a => 1
  :b => 2

julia> make_feature_space(d, 2) |> collect
2×2 Array{Tuple{Pair{Symbol,Int64},Pair{Symbol,Int64}},2}:
 (:a=>1, :a=>1)  (:a=>1, :b=>2)
 (:b=>2, :a=>1)  (:b=>2, :b=>2)

Though it's not clear from your question if you're looking for a product over the keys, values, or pairs of the dictionary.

Upvotes: 3

Related Questions