lib/multi_range.rb in multi_range-1.1.0 vs lib/multi_range.rb in multi_range-1.2.0
- old
+ new
@@ -20,28 +20,29 @@
INDEX_WITH_DEFAULT = Object.new
attr_reader :ranges
def initialize(ranges)
- @ranges = ranges.map{|s| s.is_a?(Integer) ? s..s : s }.sort_by(&:begin).freeze
+ @ranges = ranges.map{|s| s.is_a?(Numeric) ? s..s : s }.sort_by(&:begin).freeze
+ @is_float = @ranges.any?{|range| range.begin.is_a?(Float) || range.end.is_a?(Float) }
end
def merge_overlaps
return MultiRange.new([]) if @ranges.size == 0
new_ranges = []
current_range = nil
@ranges.each do |range|
next current_range = range if current_range == nil
- next if range.max <= current_range.max
+ next if range.end <= current_range.end
- if current_range.max + 1 < range.min
+ if can_combine?(current_range, range)
+ current_range = range.exclude_end? ? current_range.begin...range.end : current_range.begin..range.end
+ else
new_ranges << current_range
current_range = range
- else
- current_range = current_range.min..range.max
end
end
new_ranges << current_range
return MultiRange.new(new_ranges)
@@ -55,28 +56,30 @@
end
new_ranges = @ranges.dup
return MultiRange.new(new_ranges) if new_ranges.empty?
- return MultiRange.new(new_ranges) if other.min > @ranges.last.max # 大於最大值
- return MultiRange.new(new_ranges) if other.max < @ranges.first.min # 小於最小值
+ return MultiRange.new(new_ranges) if other.begin > @ranges.last.end # 大於最大值
+ return MultiRange.new(new_ranges) if other.end < @ranges.first.begin # 小於最小值
changed_size = 0
@ranges.each_with_index do |range, idx|
- next if other.min > range.max # 大於這個 range
- break if other.max < range.min # 小於這個 range
+ next if other.begin > range.end # 大於這個 range
+ break if other.end < range.begin # 小於這個 range
- sub_range1 = range.min...other.min
- sub_range2 = (other.max + 1)..range.max
+ sub_range1 = range.begin...other.begin
+ sub_range2_begin = other.exclude_end? ? other.end : other.end + (other.end.is_a?(Float) ? Float::EPSILON : 1)
+ sub_range2 = range.exclude_end? ? sub_range2_begin...range.end : sub_range2_begin..range.end
+
sub_ranges = []
- sub_ranges << sub_range1 if sub_range1.any?
- sub_ranges << sub_range2 if sub_range2.any?
+ sub_ranges << sub_range1 if sub_range1.begin <= sub_range1.end
+ sub_ranges << sub_range2 if sub_range2.begin <= sub_range2.end
new_ranges[idx + changed_size, 1] = sub_ranges
changed_size += sub_ranges.size - 1
- break if other.max <= range.max # 沒有超過一個 range 的範圍
+ break if other.end <= range.end # 沒有超過一個 range 的範圍
end
return MultiRange.new(new_ranges)
end
@@ -85,11 +88,11 @@
return MultiRange.new(@ranges + other_ranges).merge_overlaps
end
def overlaps?(other)
multi_range = merge_overlaps
- return multi_range.size != (multi_range - other).size
+ return multi_range.ranges != (multi_range - other).ranges
end
def sample
range = RouletteWheelSelection.sample(@ranges.map{|s| [s, s.size] }.to_h)
return nil if range == nil
@@ -137,7 +140,15 @@
end
def max
range = @ranges.last
return range.max if range
+ end
+
+ private
+
+ # make sure that range1.begin <= range2.begin
+ def can_combine?(range1, range2)
+ return range1.end >= range2.begin if @is_float
+ return range1.end + 1 >= range2.begin
end
end