Module: Enumerable

Defined in:
lib/reductions.rb

Instance Method Summary collapse

Instance Method Details

#reductions(init = nil, sym = nil, use_reduce: false, &block) ⇒ Array

Returns an Array containing all the intermediate values collected when performing Enumerable#reduce. It accepts the same parameters and block as Enumerable#reduce, with the addition of the named parameter use_reduce

WARNING: If you have monkey-patched Enumerable#reduce, you should pass use_reduce: true in the parameter list.

Examples:

# These attempt to follow the examples used for Enumerable#reduce

# Sum some numbers
(5..10).reductions(:+)                              # => [5, 11, 18, 26, 35, 45]
# Multiply some numbers
(5..10).reductions(1, :*)                           # => [1, 5, 30, 210, 1680, 15120, 151200]
# Same using a block
(5..10).reductions(1) { |product, n| product * n }  # => [1, 5, 30, 210, 1680, 15120, 151200]
# Force the use of Enumerable#reduce
(5..10).reductions(1, :*, use_reduce: true)         # => [1, 5, 30, 210, 1680, 15120, 151200]

Parameters:

  • init (Object) (defaults to: nil)

    an initial value for the reduction. Just like the one for reduce.…

  • sym (Symbol) (defaults to: nil)

    symbol representing a binary operation. Just like the one for reduce.…

  • use_reduce: (Bool) (defaults to: false)

    (named parameter) uses Enumerable#reduce in the implementation if true. Defaults to false for faster execution.

  • block (Block)

    a block to use instead of a symbol. Just like the one for reduce.…

Returns:

  • (Array)

    the array of intermediate values

Raises:

  • (LocalJumpError)


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/reductions.rb', line 34

def reductions(init=nil,sym=nil,use_reduce: false,&block)

  if sym == nil && block == nil && (init.kind_of?(Symbol) || init.kind_of?(String))
    sym = init
    init = nil
  end

  raise LocalJumpError.new("no block given") if !sym && !block

  sz = get_reductions_prealloc_size

  acc = init ? Array.new(sz + 1) : Array.new(sz)

  # Use the slower version if requested
  return reductions2(init: init,sym: sym,acc: acc,&block) if use_reduce

  # Direct access reductions with no initial value are faster than
  # each style reductions with no initial value because the latter
  # are forced to perform a boolean test at each iteration
  direct = self.respond_to?(:[])

  # presence or absence of init changes how we treat index
  # We use +yield+ rather than +block.call+ wherever possible since yield
  # executes with less overhead.
  if block && !init
    if direct
      acc[0] = self[0]
      sz -= 1
      sz.times do |j|
        acc[j+1] = yield(acc[j],self[j+1])
      end
    else
      self.each_with_index do |k,j|
        if j == 0
          acc[0] = k
        else
          acc[j] = yield(acc[j-1],k)
        end
      end
    end

  elsif block && init
    acc[0] = init
    self.each_with_index do |k,j|
      acc[j+1] = yield(acc[j],k)
    end

  elsif !block && !init
    if direct
      acc[0] = self[0]
      sz -= 1
      sz.times do |j|
        acc[j+1] = acc[j].method(sym).call(self[j+1])
      end
    else
      self.each_with_index do |k,j|
        if j == 0
          acc[0] = k
        else
          acc[j] = acc[j-1].method(sym).call(k)
        end
      end
    end

  elsif !block && init
    acc[0] = init
    self.each_with_index do |k,j|
      acc[j+1] = acc[j].method(sym).call(k)
    end
  end

  return acc
end