Module: Jinx::Collection

Overview

This Collection mix-in augments Enumerable with utility methods.

Instance Method Summary collapse

Instance Method Details

#compactEnumerable

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

Returns:

  • (Enumerable)

    an iterator over the non-nil items in this Collection



147
148
149
# File 'lib/jinx/helpers/collection.rb', line 147

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



277
278
279
# File 'lib/jinx/helpers/collection.rb', line 277

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:



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

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:



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

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 Collection but not the other Enumerable.

Returns:

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



182
183
184
# File 'lib/jinx/helpers/collection.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 Collection iterates over at least one item



60
61
62
# File 'lib/jinx/helpers/collection.rb', line 60

def empty?
  not any? { true }
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:



142
143
144
# File 'lib/jinx/helpers/collection.rb', line 142

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 Collection, or nil if this Collection is empty



67
68
69
# File 'lib/jinx/helpers/collection.rb', line 67

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:



154
155
156
# File 'lib/jinx/helpers/collection.rb', line 154

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

#hashifyHash

Returns a new Hash generated from this Collection 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:



13
14
15
16
17
# File 'lib/jinx/helpers/collection.rb', line 13

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 Collection which are also in the other Enumerable.

Returns:

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



190
191
192
# File 'lib/jinx/helpers/collection.rb', line 190

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

#join(sep = $,) ⇒ Object



218
219
220
# File 'lib/jinx/helpers/collection.rb', line 218

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 Collection, or nil if this Collection is empty



74
75
76
# File 'lib/jinx/helpers/collection.rb', line 74

def last
  detect { true }
end

#partial_sort {|item1, item2| ... } ⇒ Enumerable

Sorts this collection’s members with a partial comparator block. A partial comparator block returns -1, 0, 1 or nil. The resulting sorted order places comparable items in their relative sort order. If two items are not directly comparable, then the relative order of those items is indeterminate. In all cases the relative order is transitive, i.e.:

  • a < b and b < c => a occurs before c in the sort result

  • a > b and b > c => a occurs after c in the sort result

Examples:

sorted = [Enumerable, Array, String].partial_sort
sorted.index(Array) < sorted.index(Enumerable) #=> true
sorted.index(String) < sorted.index(Enumerable) #=> true

Yields:

  • (item1, item2)

    the partial comparison result (-1, 0, 1 or nil)

Yield Parameters:

  • item1

    an item to compare

  • item2

    another item to compare

Returns:

  • (Enumerable)

    a new collection consisting of the items in this collection in partial sort order



240
241
242
243
244
# File 'lib/jinx/helpers/collection.rb', line 240

def partial_sort(&block)
  copy = dup.to_a
  copy.partial_sort!(&block)
  copy
end

#partial_sort! {|item1, item2| ... } ⇒ Object

Sorts this collection in-place with a partial sort operator block

Yields:

  • (item1, item2)

    the partial comparison result (-1, 0, 1 or nil)

Yield Parameters:

  • item1

    an item to compare

  • item2

    another item to compare

Raises:

  • (NoMethodError)

    if this Collection does not support the sort! sort in-place method

See Also:



252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/jinx/helpers/collection.rb', line 252

def partial_sort!
  unless block_given? then return partial_sort! { |item1, item2| item1 <=> item2 } end
  # The comparison hash
  h = Hash.new { |h, k| h[k] = Hash.new }
  sort! do |a, b|
    # * If a and b are comparable, then use the comparison result.
    # * Otherwise, if there is a member c such that (a <=> c) == (c <=> b),
    #   then a <=> b has the transitive comparison result.
    # * Otherwise, a <=> b is arbitrarily set to 1.
    yield(a, b) || h[a][b] ||= -h[b][a] ||= h[a].detect_value { |c, v| v if v == yield(c, b) } || 1
  end
end

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

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

Yields:

  • (item)

    transform the item to a Comparable value

Yield Parameters:

  • item

    an enumerated item

Returns:

  • (Enumerable)

    the items in this collection in partial sort order



270
271
272
# File 'lib/jinx/helpers/collection.rb', line 270

def partial_sort_by
  partial_sort { |item1, item2| yield(item1) <=> yield(item2) }
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 Collection



82
83
84
# File 'lib/jinx/helpers/collection.rb', line 82

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

#to_compact_hashHash

Returns a new Hash generated from this Collection 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:



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

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 Collection 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:



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

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_series(conjunction = nil) ⇒ String

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

Returns:



89
90
91
# File 'lib/jinx/helpers/collection.rb', line 89

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



212
213
214
# File 'lib/jinx/helpers/collection.rb', line 212

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

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

Returns an Enumerable which iterates over items in this Collection 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 Collection

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/collection.rb', line 175

def union(other, &appender)
  Jinx::MultiEnumerator.new(self, other, &appender)
end