Project

General

Profile

Actions

Feature #18685

closed

Enumerator.product: Cartesian product of enumerables

Feature #18685: Enumerator.product: Cartesian product of enumerables

Added by knu (Akinori MUSHA) over 3 years ago. Updated almost 3 years ago.

Status:
Closed
Assignee:
-
Target version:
[ruby-core:108198]

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 of each 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


Related issues 2 (2 open0 closed)

Actions

Also available in: PDF Atom