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.1.1'

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
# File 'lib/range_compressor.rb', line 6

def compress(arg)
  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

.each_flattened(arg, &block) ⇒ Object



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

def each_flattened(arg, &block)
  if arg.class == Range && (arg.begin.nil? || arg.end.nil?)
    raise ArgumentError, 'beginless and endless Ranges are not supported'
  elsif arg.respond_to?(:each)
    arg.each { |el| each_flattened(el, &block) }
  else
    block.call(arg)
  end
end

.to_sorted_set(arg) ⇒ Object



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

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