Method: Enumerable.cross

Defined in:
lib/nano/enumerable/%3A%3Across.rb

.cross(*enums, &block) ⇒ Object

Provides the cross-product of two or more Enumerables.

This is the class-level method. The instance method
calls on this.

  Enumerable.cross([1,2], [4], ["apple", "banana"])
  #=> [[1, 4, "apple"], [1, 4, "banana"], [2, 4, "apple"], [2, 4, "banana"]]

  Enumerable.cross([1,2], [3,4])
  #=> [[1, 3], [1, 4], [2, 3], [2, 4]]


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/nano/enumerable/%3A%3Across.rb', line 18

def self.cross(*enums, &block)
  raise if enums.empty?
  gens = enums.map{|e| Generator.new(e)}
  return [] if gens.any? {|g| g.end?}
  sz = gens.size
  res = []
  tuple = Array.new(sz)

  loop do
    # fill tuple
    (0 ... sz).each { |i| 
      tuple[i] = gens[i].current 
    }
    if block.nil?
      res << tuple.dup
    else
      block.call(tuple.dup)
    end

    # step forward
    gens[-1].next
    (sz-1).downto(0) { |i|
      if gens[i].end?
        if i > 0
          gens[i].rewind
          gens[i-1].next
        else
          return res
        end
      end
    }
  end
end