module Poefy::CoreExtensions::Array::SortByDistance

Public Instance Methods

sort_by_distance_from_index(index = nil, reverse: false) click to toggle source

Take an array index and return a permutation of the items sorted by distance from that index. If 'index' is not specified, return an Enumerator of the results for all indices, in order.

The ':reverse' keyword argument switches the equally close neighbours from lowest index first to highest first. It's an option added mostly for completeness, but it's there if you need it.

# File lib/poefy/core_extensions/array.rb, line 38
def sort_by_distance_from_index index = nil, reverse: false

  # Return Enumerator of all possible output arrays.
  if index.nil?
    Enumerator.new(self.count) do |y|
      self.each.with_index do |value, index|
        y << self.sort_by_distance_from_index(index, reverse: reverse)
      end
    end

  # Return Enumerator of results for a single index.
  else
    Enumerator.new(self.count) do |y|
      y << self[index]
      counter = 0
      loop do
        counter += 1

        # Consider negative indices OOB, not from array tail.
        below_index = index - counter
        below_index = nil if below_index < 0
        below = self[below_index] if below_index

        # This is fine, uses nil as default value if OOB.
        above = self[index + counter]

        # Both the elements with index one higher and one lower
        # are equally close neighbours to the subject element.
        # The default is to output the element with the lowest
        # index first. With ':reverse' set to true, the highest
        # index is appended first.
        if reverse
          y << above if above
          y << below if below
        else
          y << below if below
          y << above if above
        end

        # Break if we're at the last element.
        break if !above and !below
      end
    end
  end
end
sort_by_distance_from_value(value = nil, reverse: false) click to toggle source

Find all elements that match 'value' and return the sort_by_distance results for all, as an Enumerator.

# File lib/poefy/core_extensions/array.rb, line 88
def sort_by_distance_from_value value = nil, reverse: false
  matching = self.each_index.select { |i| self[i] == value }
  Enumerator.new(matching.count) do |y|
    matching.each do |index|
      y << self.sort_by_distance_from_index(index, reverse: reverse)
    end
  end
end