Module: Functional::Collection

Extended by:
Collection
Included in:
Functional, Collection
Defined in:
lib/functional/collection.rb

Instance Method Summary collapse

Instance Method Details

#ascending?(data, opts = {}) {|item| ... } ⇒ true, false

Scan a collection and determine if the elements are all in ascending order. Returns true for an empty set and false for a nil sample.

When a block is given the block will be applied to both arguments. Using a block in this way allows computation against a specific field in a data set of hashes or objects.

Parameters:

  • data (Enumerable)

    the data set to search

  • opts (Hash) (defaults to: {})

    search options

Yields:

  • iterates over each element in the data set

Yield Parameters:

  • item

    each element in the data set

Returns:

  • (true, false)

    if the data set is in ascending order



299
300
301
302
303
304
305
306
307
308
309
# File 'lib/functional/collection.rb', line 299

def ascending?(data, opts={})
  return false if data.nil?
  (data.size-1).times do |i|
    if block_given?
      return false if yield(data[i]) > yield(data[i+1])
    else
      return false if data[i] > data[i+1]
    end
  end
  return true
end

#bisect_left(a, x, opts = {}) ⇒ Object

Return the index where to insert item x in list a, assuming a is sorted.

The return value i is such that all e in a have e < x, and all e in a have e >= x. So if x already appears in the list, a.insert(x) will insert just before the leftmost x already there.

Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/functional/collection.rb', line 38

def bisect_left(a, x, opts={})
  return nil if a.nil?
  return 0 if a.empty?

  lo = (opts[:lo] || opts[:low]).to_i
  hi = opts[:hi] || opts[:high] || a.length

  while lo < hi
    mid = (lo + hi) / 2
    v = (block_given? ? yield(a[mid]) : a[mid])
    if v < x
      lo = mid + 1
    else
      hi = mid
    end
  end
  return lo
end

#bisect_right(a, x, opts = {}) ⇒ Object Also known as: bisect

Return the index where to insert item x in list a, assuming a is sorted.

The return value i is such that all e in a have e <= x, and all e in a have e > x. So if x already appears in the list, a.insert(x) will insert just after the rightmost x already there.

Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched.



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/functional/collection.rb', line 69

def bisect_right(a, x, opts={})
  return nil if a.nil?
  return 0 if a.empty?

  lo = (opts[:lo] || opts[:low]).to_i
  hi = opts[:hi] || opts[:high] || a.length

  while lo < hi
    mid = (lo + hi) / 2
    v = (block_given? ? yield(a[mid]) : a[mid])
    if x < v
      hi = mid
    else
      lo = mid + 1
    end
  end
  return lo
end

#catalog_hash(data, opts = {}) {|item| ... } ⇒ Array Also known as: catalogue_hash

Convert a hash to catalog.

When a block is given the block will be applied to both arguments. Using a block in this way allows computation against a specific field in a data set of hashes or objects.

Parameters:

  • data (Enumerable)

    the data to convert

  • opts (Hash) (defaults to: {})

    search options

Yields:

  • iterates over each element in the data set

Yield Parameters:

  • item

    each element in the data set

Returns:

  • (Array)

    if the data set is in ascending order



246
247
248
249
250
251
252
253
254
# File 'lib/functional/collection.rb', line 246

def catalog_hash(data, opts={})
  return [] if data.nil? || data.empty?
  catalog = []
  data.each do |key, value|
    value = yield(value) if block_given?
    catalog << [key, value]
  end
  return catalog
end

#collect(data, opts = {}) {|item| ... } ⇒ Array

Collect sample data from a generic collection, processing each item with a block when given. Returns an array of the items from data in order.

When a block is given the block will be applied to both arguments. Using a block in this way allows computation against a specific field in a data set of hashes or objects.

Parameters:

  • data (Enumerable)

    the data set to be collected

Yields:

  • iterates over each element in the data set

Yield Parameters:

  • item

    each element in the data set

Returns:

  • (Array)

    an array of zero or more items



188
189
190
191
192
193
194
195
196
# File 'lib/functional/collection.rb', line 188

def collect(data, opts={})
  return [] if data.nil?
  sample = []
  data.each do |datum|
    datum = yield(datum) if block_given?
    sample << datum
  end
  return sample
end

#descending?(data, opts = {}) {|item| ... } ⇒ true, false

Scan a collection and determine if the elements are all in descending order. Returns true for an empty set and false for a nil sample.

When a block is given the block will be applied to both arguments. Using a block in this way allows computation against a specific field in a data set of hashes or objects.

Parameters:

  • data (Enumerable)

    the data set to search

  • opts (Hash) (defaults to: {})

    search options

Yields:

  • iterates over each element in the data set

Yield Parameters:

  • item

    each element in the data set

Returns:

  • (true, false)

    if the data set is in descending order



326
327
328
329
330
331
332
333
334
335
336
# File 'lib/functional/collection.rb', line 326

def descending?(data, opts={})
  return false if data.nil?
  (data.size-1).times do |i|
    if block_given?
      return false if yield(data[i]) < yield(data[i+1])
    else
      return false if data[i] < data[i+1]
    end
  end
  return true
end

#hash_catalog(data, opts = {}) {|item| ... } ⇒ Hash Also known as: hash_catalogue

Convert a catalog to a hash. Keeps the last value when keys are duplicated.

When a block is given the block will be applied to both arguments. Using a block in this way allows computation against a specific field in a data set of hashes or objects.

Parameters:

  • data (Enumerable)

    the data to convert

  • opts (Hash) (defaults to: {})

    search options

Yields:

  • iterates over each element in the data set

Yield Parameters:

  • item

    each element in the data set

Returns:

  • (Hash)

    if the data set is in ascending order



272
273
274
275
276
277
278
279
280
# File 'lib/functional/collection.rb', line 272

def hash_catalog(data, opts={})
  return {} if data.nil? || data.empty?
  hash = {}
  data.each do |item|
    value = (block_given? ? yield(item.last) : item.last)
    hash[item.first] = value
  end
  return hash
end

#index_and_catalog(data, opts = {}) {|item| ... } ⇒ Array Also known as: index_and_catalogue

Collect sample data from a generic collection, processing each item with a block when given. Returns an array of arrays. Each element is a two-element array where the first element is the index within the outer array and the second element is the corresponding item from within data. The elements in the returned array are in the same order as the original data collection.

When a block is given the block will be applied to both arguments. Using a block in this way allows computation against a specific field in a data set of hashes or objects.

Examples:

sample = [5, 1, 9, 3, 14, 9, 7]
Collection.catalog(sample) #=> [[0, 5], [1, 1], [2, 9], [3, 3], [4, 14], [5, 9], [6, 7]]

Parameters:

  • data (Enumerable)

    the data set to be collected

Yields:

  • iterates over each element in the data set

Yield Parameters:

  • item

    each element in the data set

Returns:

  • (Array)

    an array of zero or more items



219
220
221
222
223
224
225
226
227
228
229
# File 'lib/functional/collection.rb', line 219

def index_and_catalog(data, opts={})
  return [] if data.nil?
  sample = []
  index = 0
  data.each do |datum|
    datum = yield(datum) if block_given?
    sample << [index, datum]
    index += 1
  end
  return sample
end

#insort_left(a, x, opts = {}, &block) ⇒ Object

Insert item x in list a, and keep it sorted assuming a is sorted.

If x is already in a, insert it to the left of the leftmost x.

Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched.



100
101
102
103
104
105
106
107
108
# File 'lib/functional/collection.rb', line 100

def insort_left(a, x, opts={}, &block)
  return [x] if a.nil?
  if a.respond_to?(:dup)
    a = a.dup
  else
    a = collect(a)
  end
  return insort_left!(a, x, opts, &block)
end

#insort_left!(a, x, opts = {}, &block) ⇒ Object

Insert item x in list a, and keep it sorted assuming a is sorted. Returns a duplicate of the original list, leaving it intact.

If x is already in a, insert it to the left of the leftmost x.

Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched.



121
122
123
124
125
126
127
128
# File 'lib/functional/collection.rb', line 121

def insort_left!(a, x, opts={}, &block)
  return [x] if a.nil?
  return a << x if a.empty?

  v = (block_given? ? yield(x) : x)
  index = bisect_left(a, v, opts, &block)
  return a.insert(index, x)
end

#insort_right(a, x, opts = {}, &block) ⇒ Object Also known as: insort

Insert item x in list a, and keep it sorted assuming a is sorted. Returns a duplicate of the original list, leaving it intact.

If x is already in a, insert it to the right of the rightmost x.

Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched.



141
142
143
144
145
146
147
148
149
# File 'lib/functional/collection.rb', line 141

def insort_right(a, x, opts={}, &block)
  return [x] if a.nil?
  if a.respond_to?(:dup)
    a = a.dup
  else
    a = collect(a)
  end
  return insort_right!(a, x, opts, &block)
end

#insort_right!(a, x, opts = {}, &block) ⇒ Object Also known as: insort!

Insert item x in list a, and keep it sorted assuming a is sorted.

If x is already in a, insert it to the right of the rightmost x.

Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched.



163
164
165
166
167
168
169
170
# File 'lib/functional/collection.rb', line 163

def insort_right!(a, x, opts={}, &block)
  return [x] if a.nil?
  return a << x if a.empty?

  v = (block_given? ? yield(x) : x)
  index = bisect_right(a, v, opts, &block)
  return a.insert(index, x)
end

#random_sample(size, opts = {}) ⇒ Array

Returns a random sample of #size integers between 0 and 100 or the provided :min and/or :max options.

Parameters:

  • size (Integer)

    the size of the sample to create

  • opts (Hash) (defaults to: {})

    processing options

Options Hash (opts):

  • :min (Integer)

    the minimum value in the sample

  • :max (Integer)

    the maximun value in the sample

Returns:

  • (Array)

    an array of integers



16
17
18
19
20
21
22
23
24
# File 'lib/functional/collection.rb', line 16

def random_sample(size, opts={})
  min = opts[:min].to_i
  max = opts[:max] || 100
  sample = []
  size.times do
    sample << rand(max-min) + min
  end
  return sample
end

#slice(data, index) ⇒ Array #slice(data, start, length) ⇒ Array #slice(data, range) ⇒ Array

Override of #slice from Ruby Array. Provides a consistent interface to slice data structures that do not have a native #slice method.

Returns the element at index, or returns a subarray starting at start and continuing for length elements, or returns a subarray specified by range. Negative indices count backward from the end of the array (-1 is the last element). Returns nil if the index (or starting index) is out of range.

Overloads:

  • #slice(data, index) ⇒ Array

    Parameters:

    • data (Enumerable)

      the collection to slice

    • index (Integer)

      the index to slice

  • #slice(data, start, length) ⇒ Array

    Parameters:

    • data (Enumerable)

      the collection to slice

    • start (Integer)

      the start index for the slice

    • length (Integer)

      the length of the slice

  • #slice(data, range) ⇒ Array

    Parameters:

    • data (Enumerable)

      the collection to slice

    • range (Range)

      range of indices to include in the slice

Returns:

  • (Array)

    the slice



361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/functional/collection.rb', line 361

def slice(data, *args)
  index = args[0]
  length = args[1]
  if args.size == 1
    if index.is_a? Range
      slice_with_range(data, index)
    else
      slice_with_index(data, index)
    end
  elsif args.size == 2
    slice_with_length(data, index, length)
  else
    raise ArgumentError.new("wrong number of arguments (#{args.size} for 2..3)")
  end
end

#slice_with_index(data, index) ⇒ Object

:nodoc:



379
380
381
# File 'lib/functional/collection.rb', line 379

def slice_with_index(data, index)
  return data[index]
end

#slice_with_length(data, start, length) ⇒ Object

:nodoc:



385
386
387
388
# File 'lib/functional/collection.rb', line 385

def slice_with_length(data, start, length)
  range = Range.new(start, start+length-1)
  slice_with_range(data, range)
end

#slice_with_range(data, range) ⇒ Object

:nodoc:



392
393
394
395
396
397
398
399
400
401
# File 'lib/functional/collection.rb', line 392

def slice_with_range(data, range)
  return nil if range.first < 0 || range.first >= data.size
  last = [range.last, data.size-1].min
  range = Range.new(range.first, last)
  slice = []
  range.each do |index|
    slice << data[index]
  end
  return slice
end