Sha256: d5fab5478675c60c83eb450b52ce6c8999e5721532a5ed9b06522a1f31243f08
Contents?: true
Size: 1.53 KB
Versions: 1
Compression:
Stored size: 1.53 KB
Contents
module Enumerable 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 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 ALL_NUM = /\d+/ ALL_ALPHA = /[A-Za-z]+/ NON_ALPHANUM = /[^A-Za-z0-9]+/ 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 (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 end
Version data entries
1 entries across 1 versions & 1 rubygems
Version | Path |
---|---|
roqua-support-0.4.2 | lib/roqua/core_ext/enumerable/sort_by_alphanum.rb |