module Enumerable

Constants

ALL_ALPHA
ALL_NUM
NON_ALPHANUM

Public Instance Methods

sort_by_alphanum() { |a| ... } click to toggle source
# File lib/roqua/core_ext/enumerable/sort_by_alphanum.rb, line 2
def sort_by_alphanum
  sort do |a, b|
    if block_given?
      grouped_compare(yield(a), yield(b))
    else
      grouped_compare(a, b)
    end
  end
end
sort_by_alphanum!() { |a| ... } click to toggle source
# File lib/roqua/core_ext/enumerable/sort_by_alphanum.rb, line 12
def sort_by_alphanum!
  sort! do |a, b|
    if block_given?
      grouped_compare(yield(a), yield(b))
    else
      grouped_compare(a, b)
    end
  end
end

Private Instance Methods

grouped_compare(a, b) click to toggle source
# File lib/roqua/core_ext/enumerable/sort_by_alphanum.rb, line 28
def grouped_compare(a, b)
  a_scanner = StringScanner.new(a)
  b_scanner = StringScanner.new(b)
  # each loop has to do exactly 1 non-nil-scan on both scanners or return a non-zero value.
  loop do
    ret = \
      if a_scanner.eos?
        -1
      elsif b_scanner.eos?
        1
      elsif (a_chunk = a_scanner.scan(ALL_NUM))
        if (b_chunk = b_scanner.scan(ALL_NUM))
          if a_chunk.to_i != b_chunk.to_i
            a_chunk.to_i <=> b_chunk.to_i
          else # 03 vs 3
            a_chunk <=> b_chunk
          end
        elsif b_scanner.scan(ALL_ALPHA)
          -1
        else # NON_ALPHANUM
          1
        end
      elsif (a_chunk = a_scanner.scan(ALL_ALPHA))
        if (b_chunk = b_scanner.scan(ALL_ALPHA))
          a_chunk <=> b_chunk
        else # ALL_NUM or NON_ALPHANUM
          1
        end
      else # NON_ALPHANUM
        a_chunk = a_scanner.scan(NON_ALPHANUM)
        if (b_chunk = b_scanner.scan(NON_ALPHANUM))
          a_chunk <=> b_chunk
        else
          -1
        end
      end
    return ret if ret != 0
  end
end