Class: Tap::Support::Combinator

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/tap/support/combinator.rb

Overview

Combinator provides a method for iterating over all combinations of items in the input sets.

c = Combinator.new [1,2], [3,4]
c.to_a            # => [[1,3], [1,4], [2,3], [2,4]]

Combinators can take any object that responds to each as an input set; normally arrays are used.

Implementation

Combinator iteratively combines each element from the first set (a) with each element from the second set (b). When more than two sets are given, the second and remaining sets are bundled into a Combinator, which then acts as the second set.

c = Combinator.new [1,2], [3,4], [5,6]
c.a               # => [[1],[2]]
c.b.class         # => Combinator
c.b.a             # => [[3],[4]]
c.b.b             # => [[5],[6]]

Note that internally each item in a set is stored as a single-item array; the arrays are added during combination. Thus when iterating, the combinations are calculated like:

([1] + [3]) + [5] # => [1,3,5]

This is probably not the fastest implementation, but it works.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*sets) ⇒ Combinator

Creates a new Combinator. Each input must respond to each, or be nil.



46
47
48
49
# File 'lib/tap/support/combinator.rb', line 46

def initialize(*sets)
  @a = make_set(sets.shift)
  @b = make_set(*sets)
end

Instance Attribute Details

#aObject (readonly)

The first set



39
40
41
# File 'lib/tap/support/combinator.rb', line 39

def a
  @a
end

#bObject (readonly)

The second set



42
43
44
# File 'lib/tap/support/combinator.rb', line 42

def b
  @b
end

Instance Method Details

#eachObject

Passes each combination as an array to the input block.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/tap/support/combinator.rb', line 74

def each # :yields: combination
  case
  when !(@a.empty? || @b.empty?)
    @a.each do |a|
      @b.each do |b|
        yield(a + b)
      end
    end
  when @a.empty? 
    @b.each {|b| yield(b) }
  when @b.empty? 
    @a.each {|a| yield(a) }
  end
end

#empty?Boolean

True if length is zero.

Returns:

  • (Boolean)


57
58
59
# File 'lib/tap/support/combinator.rb', line 57

def empty?
  a.empty? && b.empty?
end

#lengthObject

Returns the number of combinations returned by each.



62
63
64
65
66
67
68
69
70
71
# File 'lib/tap/support/combinator.rb', line 62

def length
  case
  when !(@a.empty? || @b.empty?)
    @a.length * @b.length
  when @a.empty? 
    @b.length
  when @b.empty?
    @a.length
  end
end

#setsObject

Returns the sets used to initialize the Combinator.



52
53
54
# File 'lib/tap/support/combinator.rb', line 52

def sets
  sets_in(a) + sets_in(b)
end