class Trusty::Sorting::AtomSorter

Constants

BOTH_EQUAL
COMPARERS
LEFT_FIRST
NUMERIC_RE
PATTERNS_RE

/(?<=^|s)[d.]+|+|.+?/ /(?<=^|s)[d.]+|+|[^d.-]+|+/

RIGHT_FIRST

Attributes

index[R]
value[R]

Public Class Methods

add_comparer(left_type, right_type, &comparer) click to toggle source
# File lib/trusty/sorting/atom_sorter.rb, line 58
def add_comparer(left_type, right_type, &comparer)
  COMPARERS[comparer_key_for(left_type, right_type)] = comparer_builder(left_type, right_type, &comparer)
end
compare_values(left_value, right_value) click to toggle source
# File lib/trusty/sorting/atom_sorter.rb, line 33
def compare_values(left_value, right_value)
  if left_value.class == right_value.class
    left_value <=> right_value
  elsif comparer = COMPARERS[comparer_key_for(left_value.class, right_value.class)]
    comparer.call(left_value, right_value)
  else
    raise "No comparer defined for #{left_value.class} <=> #{right_value.class}"
  end
end
new(value, index) click to toggle source
# File lib/trusty/sorting/atom_sorter.rb, line 22
def initialize(value, index)
  @value, @index = value, index
end
parse(string) click to toggle source

Loosely based on stackoverflow.com/a/4079031

# File lib/trusty/sorting/atom_sorter.rb, line 44
def parse(string)
  string.scan(PATTERNS_RE).each_with_index.map do |atom, index|
    if    !atom.match(NUMERIC_RE) then  new(normalize_string(atom), index)
    elsif !atom.include?('.')     then  new(atom.to_i, index)
    elsif atom.include?('-')      then  new(atom.to_f, index)
    else                                new(Atoms::Version.new(atom), index)
    end
  end
end
sort(list) click to toggle source
# File lib/trusty/sorting/atom_sorter.rb, line 54
def sort(list)
  list.sort_by{ |item| parse(item) }
end

Private Class Methods

check_result(left_value, right_value, if_this, then_that) click to toggle source
# File lib/trusty/sorting/atom_sorter.rb, line 78
def check_result(left_value, right_value, if_this, then_that)
  result = left_value <=> right_value
  if_this == result ? then_that : result
end
comparer_builder(left_type, right_type, &comparer) click to toggle source
# File lib/trusty/sorting/atom_sorter.rb, line 68
def comparer_builder(left_type, right_type, &comparer)
  ->(left_value, right_value) do
    if left_value.is_a?(left_type)
      comparer.call(left_value, right_value)
    else
      -comparer.call(right_value, left_value)
    end
  end
end
comparer_key_for(*types) click to toggle source
# File lib/trusty/sorting/atom_sorter.rb, line 83
def comparer_key_for(*types)
  types.map(&:to_s).sort
end
normalize_string(string) click to toggle source
# File lib/trusty/sorting/atom_sorter.rb, line 64
def normalize_string(string)
  ActiveSupport::Inflector.transliterate(string).downcase
end

Public Instance Methods

<=>(other) click to toggle source
# File lib/trusty/sorting/atom_sorter.rb, line 26
def <=>(other)
  other.is_a?(self.class) || raise("#{self.class} can only compare with classes of the same kind")

  self.class.compare_values(self.value, other.value)
end