Module: BerkeleyLibrary::Util::Arrays

Extended by:
Arrays
Included in:
Arrays
Defined in:
lib/berkeley_library/util/arrays.rb

Instance Method Summary collapse

Instance Method Details

#count_while(arr: ) ⇒ Enumerator #count_while(arr: , &block) ⇒ Integer

Counts how many contiguous elements from the start of an sequence of values satisfy the given block.

Overloads:

  • #count_while(arr: ) ⇒ Enumerator

    Returns an enumerator.

    Parameters:

    • values (Enumerable)

      the values

    Returns:

    • (Enumerator)

      the enumerator.

  • #count_while(arr: , &block) ⇒ Integer

    Passes elements to the block until the block returns nil or false, then stops iterating and returns the count of matching elements.

    Parameters:

    • values (Enumerable)

      the values

    Returns:

    • (Integer)

      the count



32
33
34
35
36
37
38
39
40
41
# File 'lib/berkeley_library/util/arrays.rb', line 32

def count_while(values:)
  return to_enum(:count_while, values: values) unless block_given?

  values.inject(0) do |count, x|
    matched = yield x
    break count unless matched

    count + 1
  end
end

#find_index(value, in_array: , start_index: ) ⇒ Integer? #find_index(&block) ⇒ Integer? #find_indexEnumerator

Given a block or a value, finds the index of the first matching value at or after the specified start index.

Overloads:

  • #find_index(value, in_array: , start_index: ) ⇒ Integer?

    Finds the first index of the specified value.

    Parameters:

    • value (Object)

      the value to find

    • in_array (Array) (defaults to: )

      the array to search

    • start_index (Integer) (defaults to: )

      the index to start with

    Returns:

    • (Integer, nil)

      the index, or nil if no value matches

  • #find_index(&block) ⇒ Integer?

    Finds the index of the first value matching the specified block.

    Parameters:

    • in_array (Array)

      the array to search

    • start_index (Integer)

      the index to start with

    Yield Returns:

    • (Boolean)

      whether the element matches

    Returns:

    • (Integer, nil)

      the index, or nil if no value matches

  • #find_indexEnumerator

    Returns a new enumerator.

    Parameters:

    • in_array (Array)

      the array to search

    • start_index (Integer)

      the index to start with

    Returns:

    • (Enumerator)

      a new enumerator

Raises:

  • (ArgumentError)


92
93
94
95
96
97
98
# File 'lib/berkeley_library/util/arrays.rb', line 92

def find_index(*args, in_array:, start_index: 0, &block)
  raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 0..1" if args.size > 1
  return Enumerator.new { |y| find_index(in_array: in_array, start_index: start_index, &y) } if args.empty? && !block_given?
  return unless (relative_index = in_array[start_index..].find_index(*args, &block))

  relative_index + start_index
end

#find_indices(for_array: , in_array: ) ⇒ Array<Integer>? #find_indices(for_array: , in_array: ) {|source, target| ... } ⇒ Array<Integer>?

Given two lists, one of which is a superset of the other, with elements in the same order (but possibly with additional elements in the superset), returns an array the length of the subset, containing for each element in the subset the index of the corresponding element in the superset.

Overloads:

  • #find_indices(for_array: , in_array: ) ⇒ Array<Integer>?

    For each value in for_array, finds the index of the first equal value in in_array after the previously matched value.

    Parameters:

    • in_array (Array) (defaults to: )

      the list of values to look in

    • for_array (Array) (defaults to: )

      the values to look for

    Returns:

    • (Array<Integer>, nil)

      the indices in in_array of each value in for_array, or nil if not all values could be found

  • #find_indices(for_array: , in_array: ) {|source, target| ... } ⇒ Array<Integer>?

    For each value in for_array, finds the index of the first value in in_array after the previously matched value that matches the specified match function.

    Parameters:

    • in_array (Array) (defaults to: )

      the list of values to look in

    • for_array (Array) (defaults to: )

      the values to look for

    Yield Parameters:

    • source (Object)

      the value to compare

    • target (Object)

      the value to compare against

    Returns:

    • (Array<Integer>, nil)

      the indices in in_array of each value in for_array, or nil if not all values could be found



66
67
68
69
70
# File 'lib/berkeley_library/util/arrays.rb', line 66

def find_indices(for_array:, in_array:, &block)
  return find_indices_matching(for_array, in_array, &block) if block_given?

  find_all_indices(for_array, in_array)
end

#invert(arr) ⇒ Array<Integer, nil>?

Given an array of unique integers a1, returns a new array a2 in which the value at each index i2 is the index i1 at which that value was found in a1. E.g., given [0, 2, 3], returns [0, nil, 1, 2]. The indices need not be in order but must be unique.

Parameters:

  • arr (Array<Integer>, nil)

    the array to invert.

Returns:

  • (Array<Integer, nil>, nil)

    the inverted array, or nil if the input array is nil

Raises:

  • TypeError if arr is not an array of integers

  • ArgumentError if arr contains duplicate values



110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/berkeley_library/util/arrays.rb', line 110

def invert(arr)
  return unless arr

  # noinspection RubyNilAnalysis
  Array.new(arr.size).tap do |inv|
    arr.each_with_index do |v, i|
      next inv[v] = i unless (prev_index = inv[v])

      raise ArgumentError, "Duplicate value #{v} at index #{i} already found at #{prev_index}"
    end
  end
end

#merge(a1, a2) ⇒ Array

Merges two arrays in an order-preserving manner.

Parameters:

  • a1 (Array)

    the first array

  • a2 (Array)

    the second array

Returns:

  • (Array)

    a merged array that is an ordered superset of both a1 and a2

See Also:



128
129
130
131
132
133
134
# File 'lib/berkeley_library/util/arrays.rb', line 128

def merge(a1, a2)
  return a1 if a2.empty?
  return a2 if a1.empty?

  shorter, longer = a1.size > a2.size ? [a2, a1] : [a1, a2]
  do_merge(shorter, longer)
end

#ordered_superset?(superset:, subset:) ⇒ Boolean

Recursively checks whether the specified list contains, in the same order, all values in the other specified list (additional codes in between are fine)

Parameters:

  • subset (Array)

    the values to look for

  • superset (Array)

    the list of values to look in

Returns:

  • (Boolean)

    boolean True if all values were found, false otherwise



16
17
18
# File 'lib/berkeley_library/util/arrays.rb', line 16

def ordered_superset?(superset:, subset:)
  !find_indices(in_array: superset, for_array: subset).nil?
end