class RangeRegexp::Converter
Public Class Methods
new(range)
click to toggle source
# File lib/range_regexp.rb, line 6 def initialize(range) @min = range.first @max = range.last @negative_subpatterns = [] @positive_subpatterns = [] init_negative_subpatterns init_positive_subpatterns end
Public Instance Methods
convert()
click to toggle source
# File lib/range_regexp.rb, line 17 def convert @regexp ||= begin negative_subpatterns_only = arrays_diff(@negative_subpatterns, @positive_subpatterns).map do |pattern| "-#{pattern}" end positive_subpatterns_only = arrays_diff(@positive_subpatterns, @negative_subpatterns) intersected_subpatterns = (@positive_subpatterns & @negative_subpatterns).map do |pattern| "-?#{pattern}" end Regexp.new("#{(negative_subpatterns_only + intersected_subpatterns + positive_subpatterns_only).join('|')}") end end
Private Instance Methods
arrays_diff(a, b)
click to toggle source
# File lib/range_regexp.rb, line 32 def arrays_diff(a, b) a - (a & b) end
fill_by_nines(int, nines_count)
click to toggle source
# File lib/range_regexp.rb, line 81 def fill_by_nines(int, nines_count) "#{int.to_s[0...-nines_count]}#{'9' * nines_count}".to_i end
fill_by_zeros(int, zeros_count)
click to toggle source
# File lib/range_regexp.rb, line 85 def fill_by_zeros(int, zeros_count) int - int % 10 ** zeros_count end
init_negative_subpatterns()
click to toggle source
# File lib/range_regexp.rb, line 36 def init_negative_subpatterns if @min < 0 @negative_subpatterns = split_to_patterns(@max < 0 ? @max.abs : 1, @min.abs) @min = 0 end end
init_positive_subpatterns()
click to toggle source
# File lib/range_regexp.rb, line 43 def init_positive_subpatterns if @max >= 0 @positive_subpatterns = split_to_patterns(@min, @max) end end
range_to_pattern(start, stop)
click to toggle source
# File lib/range_regexp.rb, line 89 def range_to_pattern(start, stop) pattern = '' any_digit_count = 0 start.to_s.split('').zip(stop.to_s.split('')).each do |(start_digit, stop_digit)| if start_digit == stop_digit pattern += start_digit elsif start_digit != '0' || stop_digit != '9' pattern += "[#{start_digit}-#{stop_digit}]" else any_digit_count += 1 end end pattern += '\d' if any_digit_count > 0 pattern += "{#{any_digit_count}}" if any_digit_count > 1 pattern end
split_to_patterns(min, max)
click to toggle source
# File lib/range_regexp.rb, line 49 def split_to_patterns(min, max) subpatterns = [] start = min split_to_ranges(min, max).each do |stop| subpatterns.push(range_to_pattern(start, stop)) start = stop + 1 end subpatterns end
split_to_ranges(min, max)
click to toggle source
# File lib/range_regexp.rb, line 59 def split_to_ranges(min, max) stops = Set.new stops.add(max) nines_count = 1 stop = fill_by_nines(min, nines_count) while min <= stop && stop < max stops.add(stop) nines_count += 1 stop = fill_by_nines(min, nines_count) end zeros_count = 1 stop = fill_by_zeros(max + 1, zeros_count) - 1 while min < stop && stop <= max stops.add(stop) zeros_count += 1 stop = fill_by_zeros(max + 1, zeros_count) - 1 end stops.to_a.sort end