Module: Enumerable

Included in:
Jinx::AttributeEnumerator, Jinx::Collection, Jinx::ReferenceEnumerator, Jinx::Visitor::VisitorEnumerator
Defined in:
lib/jinx/helpers/enumerate.rb,
lib/jinx/helpers/collection.rb,
lib/jinx/helpers/enumerable.rb,
lib/jinx/helpers/pretty_print.rb,
lib/jinx/helpers/transitive_closure.rb

Instance Method Summary collapse

Instance Method Details

#collection?Boolean

Overrides Object#collection? to returns true, since an Enumerable is capable of holding heterogenous items by default. Subclasses can override this method.

Returns:

  • (Boolean)


12
13
14
# File 'lib/jinx/helpers/collection.rb', line 12

def collection?
  true
end

#compactEnumerable

Returns an iterator over the non-nil items in this Enumerable.

Returns:

  • (Enumerable)

    an iterator over the non-nil items in this Enumerable



148
149
150
# File 'lib/jinx/helpers/enumerable.rb', line 148

def compact
  filter { |item| not item.nil? }
end

#compact_map {|item| ... } ⇒ Enumerable

Returns the mapped values excluding null values.

Yields:

  • (item)

    the transformer on the enumerated items

Yield Parameters:

  • item

    an enumerated item

Returns:

  • (Enumerable)

    the mapped values excluding null values



242
243
244
# File 'lib/jinx/helpers/enumerable.rb', line 242

def compact_map(&mapper)
  wrap(&mapper).compact
end

#detect_valueObject

Returns the first non-nil, non-false enumerated value resulting from a call to the block given to this method, or nil if no value detected.

Examples:

[1, 2].detect_value { |item| item / 2 if item % 2 == 0 } #=> 1

Returns:

  • (Object)

    the detected block result

See Also:



101
102
103
104
105
106
107
# File 'lib/jinx/helpers/enumerable.rb', line 101

def detect_value
  each do |*item|
    value = yield(*item)
    return value if value
  end
  nil
end

#detect_with_value(Object, Object)

Returns the first item and value for which an enumeration on the block given to this method returns a non-nil, non-false value.

Examples:

[1, 2].detect_with_value { |item| item / 2 if item % 2 == 0 } #=> [2, 1]

Returns:

See Also:



116
117
118
119
120
121
122
# File 'lib/jinx/helpers/enumerable.rb', line 116

def detect_with_value
  value = nil
  match = detect do |*item|
    value = yield(*item)
  end
  [match, value]
end

#difference(other) ⇒ Object Also known as: -

Returns an Enumerable which iterates over items in this Enumerable but not the other Enumerable.

Returns:

  • an Enumerable which iterates over items in this Enumerable but not the other Enumerable



182
183
184
# File 'lib/jinx/helpers/enumerable.rb', line 182

def difference(other)
  filter { |item| not other.include?(item) }
end

#empty?Boolean

This method is functionally equivalent to to_a.empty but is more concise and efficient.

Returns:

  • (Boolean)

    whether this Enumerable iterates over at least one item



61
62
63
# File 'lib/jinx/helpers/enumerable.rb', line 61

def empty?
  not any? { true }
end

#enumerate {|item| ... } ⇒ Object

Synonym for each.

Yields:

  • (item)

    the block to apply to each member

Yield Parameters:

  • item

    a member of this Enumerable



27
28
29
# File 'lib/jinx/helpers/enumerate.rb', line 27

def enumerate(&block)
  each(&block)
end

#filter {|item| ... } ⇒ Enumerable

Returns a new Enumerable that iterates over the base Enumerable items for which filter evaluates to a non-nil,

non-false value, e.g.:
 [1, 2, 3].filter { |n| n != 2 }.to_a #=> [1, 3]

Unlike select, filter reflects changes to the base Enumerable, e.g.:

a = [1, 2, 3]
filter = a.filter { |n| n != 2 }
a << 4
filter.to_a #=> [1, 3, 4]

In addition, filter has a small, fixed storage requirement, making it preferable to select for large collections. Note, however, that unlike select, filter does not return an Array. The default filter block returns the passed item.

Examples:

[1, nil, 3].filter.to_a #=> [1, 3]

Yields:

  • (item)

    filter the selection filter

Yield Parameters:

  • item

    the collection member to filter

Returns:



143
144
145
# File 'lib/jinx/helpers/enumerable.rb', line 143

def filter(&filter)
  Jinx::Filter.new(self, &filter)
end

#firstObject

This method is functionally equivalent to to_a.first but is more concise and efficient.

Returns:

  • the first enumerated item in this Enumerable, or nil if this Enumerable is empty



68
69
70
# File 'lib/jinx/helpers/enumerable.rb', line 68

def first
  detect { true }
end

#flattenEnumerable

Returns the flattened result.

Examples:

{:a => {:b => :c}, :d => [:e]}.enum_values.flatten.to_a #=> [:b, :c, :e]

Returns:



155
156
157
# File 'lib/jinx/helpers/enumerable.rb', line 155

def flatten
  Jinx::Flattener.new(self).to_a
end

#hashifyHash

Returns a new Hash generated from this Enumerable and an optional value generator block. This Enumerable contains the Hash keys. If the value generator block is given to this method then the block is called with each enumerated element as an argument to generate the associated hash value. If no block is given, then the values are nil.

Examples:

[1, 2, 3].hashify { |item| item.modulo(2) } #=> { 1 => 1, 2 => 0, 3 => 1 }
[:a].hashify #=> { :a => nil }

Returns:



14
15
16
17
18
# File 'lib/jinx/helpers/enumerable.rb', line 14

def hashify
  hash = {}
  each { |item| hash[item] = yield item if block_given? }
  hash
end

#intersect(other) ⇒ Object Also known as: &

Returns an Enumerable which iterates over items in this Enumerable which are also in the other Enumerable.

Returns:

  • an Enumerable which iterates over items in this Enumerable which are also in the other Enumerable



189
190
191
# File 'lib/jinx/helpers/enumerable.rb', line 189

def intersect(other)
  filter { |item| other.include?(item) }
end

#join(sep = $,) ⇒ Object



216
217
218
# File 'lib/jinx/helpers/enumerable.rb', line 216

def join(sep = $,)
  to_a.join(sep)
end

#lastObject

This method is functionally equivalent to to_a.last but is more concise and efficient.

Returns:

  • the last enumerated item in this Enumerable, or nil if this Enumerable is empty



75
76
77
# File 'lib/jinx/helpers/enumerable.rb', line 75

def last
  detect { true }
end

#partial_sortEnumerable

Sorts this collection’s members with a partial sort operator, i.e. the comparison returns -1, 0, 1 or nil. The resulting sorted order places each non-nil comparable items in the sort order. The order of nil comparison items is indeterminate.

Examples:

[Array, Numeric, Enumerable, Set].partial_sort #=> [Array, Numeric, Set, Enumerable]

Returns:

  • (Enumerable)

    the items in this collection in partial sort order



227
228
229
230
# File 'lib/jinx/helpers/enumerable.rb', line 227

def partial_sort
  unless block_given? then return partial_sort { |item1, item2| item1 <=> item2 } end
  sort { |item1, item2| yield(item1, item2) or 1 }
end

#partial_sort_byEnumerable

Sorts this collection’s members with a partial sort operator on the results of applying the block.

Returns:

  • (Enumerable)

    the items in this collection in partial sort order



235
236
237
# File 'lib/jinx/helpers/enumerable.rb', line 235

def partial_sort_by
  partial_sort { |item1, item2| yield(item1) <=> yield(item2) }
end

#pp_s(opts = nil) {|item| ... } ⇒ Object

If a transformer block is given to this method, then the block is applied to each enumerated item before pretty-printing the result.

Parameters:

  • opts (Hash, Symbol, nil) (defaults to: nil)

    the print options

Yields:

  • (item)

    transforms the item to print

Yield Parameters:

  • item

    the item to print



132
133
134
135
136
137
138
139
# File 'lib/jinx/helpers/pretty_print.rb', line 132

def pp_s(opts=nil)
  # delegate to Object if no block
  return super unless block_given?
  # make a print wrapper
  wrapper = PrintWrapper.new { |item| yield item }
  # print using the wrapper on each item
  wrap { |item| wrapper.wrap(item) }.pp_s(opts)
end

#pretty_print(q) ⇒ Object

Pretty-prints the content within brackets, as is done by the Array pretty printer.



142
143
144
145
146
147
148
# File 'lib/jinx/helpers/pretty_print.rb', line 142

def pretty_print(q)
  q.group(1, '[', ']') {
    q.seplist(self) { |v|
      q.pp v
    }
  }
end

#pretty_print_cycle(q) ⇒ Object

Pretty-prints the cycle within brackets, as is done by the Array pretty printer.



151
152
153
# File 'lib/jinx/helpers/pretty_print.rb', line 151

def pretty_print_cycle(q)
  q.text(empty? ? '[]' : '[...]')
end

#qp(opts = nil) ⇒ String

Prints this Enumerable with a filter that calls qp on each item. Non-collection Enumerable classes override this method to delegate to Object#qp.

Unlike Object#qp, this implementation accepts the Object#pp_s options. The options are used to format this Enumerable, but are not propagated to the enumerated items.

Parameters:

  • opts (Hash, Symbol, nil) (defaults to: nil)

    the print options

Returns:

  • (String)

    the formatted result



121
122
123
# File 'lib/jinx/helpers/pretty_print.rb', line 121

def qp(opts=nil)
  wrap { |item| item.qp }.pp_s(opts)
end

#sizeInteger Also known as: length

This method is functionally equivalent to to_a.size but is more concise and efficient for an Enumerable which does not implement the #size method.

Returns:

  • (Integer)

    the count of items enumerated in this Enumerable



83
84
85
# File 'lib/jinx/helpers/enumerable.rb', line 83

def size
  inject(0) { |size, item| size + 1 }
end

#to_compact_hashHash

Returns a new Hash generated from this Enumerable and a required value generator block. This Enumerable contains the Hash keys. The block is called with each enumerated element as an argument to generate the associated hash value. Only non-nil, non-empty values are included in the hash.

Examples:

[1, 2, 3].to_compact_hash { |item| item.modulo(2) } #=> { 1 => 1, 2 => 0, 3 => 1 }
[1, 2, 3].to_compact_hash { |n| n.modulo(2) unless item > 2 } #=> {1 => 1, 2 => 0}
[1, 2, 3].to_compact_hash { |n| n > 2 } #=> {1 => false, 2 => false, 3 => true}
[1, 2, 3].to_compact_hash { |n| Array.new(n - 1, n) } #=> {2 => [2], 3 => [2, 3]}

Returns:

Raises:

  • (ArgumentError)

    if the generator block is not given

See Also:



33
34
35
36
# File 'lib/jinx/helpers/enumerable.rb', line 33

def to_compact_hash
  raise ArgumentError.new("Compact hash builder is missing the value generator block") unless block_given?
  to_compact_hash_with_index { |item, index| yield item }
end

#to_compact_hash_with_index {|item, index| ... } ⇒ Hash

Returns a new Hash generated from this Enumerable with a block whose arguments include the enumerated item and its index. Every value which is nil or empty is excluded.

Examples:

[1, 2, 3].to_compact_hash_with_index { |item, index| item + index } #=> { 1 => 1, 2 => 3, 3 => 5 }

Yields:

  • (item, index)

    the hash value

Yield Parameters:

  • item

    the enumerated value

  • index

    the enumeration index

Returns:



47
48
49
50
51
52
53
54
55
56
# File 'lib/jinx/helpers/enumerable.rb', line 47

def to_compact_hash_with_index
  hash = {}
  self.each_with_index do |item, index|
    next if item.nil?
    value = yield(item, index)
    next if value.nil_or_empty?
    hash[item] = value
  end
  hash
end

#to_enumObject

Returns self.

Returns:

  • self



32
33
34
# File 'lib/jinx/helpers/enumerate.rb', line 32

def to_enum
  self
end

#to_series(conjunction = nil) ⇒ String

Returns the content of this Enumerable as a series using Array#to_series.

Returns:



90
91
92
# File 'lib/jinx/helpers/enumerable.rb', line 90

def to_series(conjunction=nil)
  to_a.to_series
end

#transform {|item| ... } ⇒ Enumerable Also known as: wrap

transformed = a.wrap { |n| n * 2 }

a << 4
transformed.to_a #=> [2, 4, 6, 8]

In addition, transform has a small, fixed storage requirement, making it preferable to select for large collections. Note, however, that unlike map, transform does not return an Array.

Yields:

  • (item)

    the transformer on the enumerated items

Yield Parameters:

  • item

    an enumerated item

Returns:

  • (Enumerable)

    an enumeration on the transformed values



210
211
212
# File 'lib/jinx/helpers/enumerable.rb', line 210

def transform(&mapper)
  Jinx::Transformer.new(self, &mapper)
end

#transitive_closure(method = nil) ⇒ Object

Returns the transitive closure over all items in this Enumerable.



45
46
47
48
49
50
51
52
# File 'lib/jinx/helpers/transitive_closure.rb', line 45

def transitive_closure(method=nil)
  # delegate to Object if there is a method argument
  return super(method) if method
  # this Enumerable's children are this Enumerable's contents
  closure = super() { |node| node.equal?(self) ? self : yield(node) }
  # remove this collection from the closure
  closure[1..-1]
end

#union(other) ⇒ Enumerable Also known as: +

Returns an Enumerable which iterates over items in this Enumerable and the other Enumerable in sequence. Unlike the Array plus (+) operator, #union reflects changes to the underlying enumerators.

Examples:

a = [1, 2]
b = [4, 5]
ab = a.union(b)
ab #=> [1, 2, 4, 5]
a << 3
a + b #=> [1, 2, 4, 5]
ab #=> [1, 2, 3, 4, 5]

Parameters:

  • other (Enumerable)

    the Enumerable to compose with this Enumerable

Returns:

  • (Enumerable)

    an enumerator over self followed by other

Technology idiosyncracy:

  • Cucumber

    Cucumber defines it’s own Enumerable union monkey-patch. Work around this in the short term by trying to call the super first.



175
176
177
# File 'lib/jinx/helpers/enumerable.rb', line 175

def union(other)
  super rescue Jinx::MultiEnumerator.new(self, other)
end