Actions
Feature #18685
closedEnumerator.product: Cartesian product of enumerables
Description
I'd like to add a new Enumerator class method for generating the Cartesian product of given enumerators.
A product here does not mean an accumulated array of arrays, but an enumerator to enumerate all combinations.
product = Enumerator.product(1..3, ["A", "B"])
p product.class #=> Enumerator
product.each do |i, c|
puts "#{i}-#{c}"
end
=begin output
1-A
1-B
2-A
2-B
3-A
3-B
=end
This can be used to reduce nested blocks and allows for iterating over an indefinite number of enumerable objects.
Implementation notes¶
-
It should internally use
each_entry
instead ofeach
on enumerable objects to make sure to capture all yielded arguments. -
If no enumerable object is given, the block is called once with no argument.
-
It should reject a keyword-style hash argument so we can add keyword arguments in the future without breaking existing code.
-
Here's an example implementation:
# call-seq: # Enumerator.product(*enums) -> enum # Enumerator.product(*enums) { |*args| block } -> return value of args[0].each_entry {} def Enumerator.product(*enums, **nil, &block) # TODO: size should be calculated if possible return to_enum(__method__, *enums) if block.nil? enums.reverse.reduce(block) { |inner, enum| ->(*values) { enum.each_entry { |value| inner.call(*values, value) } } }.call() end
-
Not to be confused with
Enumerator.produce
. 😝
Prior case¶
Actions
Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0