Module: RangeCompressor

Defined in:
lib/range_compressor.rb,
lib/range_compressor/version.rb

Constant Summary collapse

SORTED_SET_CLASSES =
%w[
  CharacterSet
  CharacterSet::Pure
  ImmutableSet
  RBTree
  SortedSet
].freeze
VERSION =
'1.2.0'

Class Method Summary collapse

Class Method Details

.compress(arg) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/range_compressor.rb', line 6

def compress(arg)
  # make contents flat, unique, and sorted
  sorted_set = to_sorted_set(arg)

  ranges = []
  previous = nil
  current_start = nil
  current_end = nil

  sorted_set.each do |object|
    if previous.nil?
      current_start = object
    elsif previous.next != object
      # gap found, finalize previous range
      ranges << (current_start..current_end)
      current_start = object
    end
    current_end = object
    previous = object
  end

  # add final range
  ranges << (current_start..current_end) if current_start

  ranges
end

.flatten(arg, hash) ⇒ Object



55
56
57
58
59
60
61
62
63
64
# File 'lib/range_compressor.rb', line 55

def flatten(arg, hash)
  if arg.respond_to?(:each)
    if arg.instance_of?(Range) && (arg.begin.nil? || arg.end.nil?)
      raise ArgumentError, 'beginless and endless Ranges are not supported'
    end
    arg.each { |el| flatten(el, hash) }
  else
    hash[arg] = true
  end
end

.to_sorted_set(arg) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/range_compressor.rb', line 41

def to_sorted_set(arg)
  if arg.nil?
    []
  elsif (arg.class.ancestors.map(&:to_s) & SORTED_SET_CLASSES).any?
    arg
  elsif arg.respond_to?(:each)
    hash = {}
    flatten(arg, hash)
    hash.keys.sort
  else
    raise(ArgumentError, 'value must be enumerable')
  end
end