lib/multi_range.rb in multi_range-0.0.4 vs lib/multi_range.rb in multi_range-1.0.0
- old
+ new
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
require 'multi_range/version'
require 'roulette-wheel-selection'
if not Range.method_defined?(:size)
warn "Please backports Range#size method to use multi_range gem.\n" \
@@ -17,16 +19,16 @@
class MultiRange
INDEX_WITH_DEFAULT = Object.new
attr_reader :ranges
- def initialize(ranges) # range 要由小到大排序,且各 range 不能重疊
- @ranges = ranges.map{|s| s.is_a?(Integer) ? s..s : s }.freeze
+ def initialize(ranges)
+ @ranges = ranges.map{|s| s.is_a?(Integer) ? s..s : s }.sort_by(&:begin).freeze
end
def flatten
- return if @ranges.size == 0
+ return MultiRange.new([]) if @ranges.size == 0
new_ranges = []
current_range = nil
@ranges.each do |range|
@@ -44,10 +46,16 @@
new_ranges << current_range
return MultiRange.new(new_ranges)
end
def -(other)
+ if other.is_a?(MultiRange)
+ new_multi_range = dup
+ other.ranges.each{|range| new_multi_range -= range }
+ return new_multi_range
+ 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 # 小於最小值
@@ -68,9 +76,19 @@
changed_size += sub_ranges.size - 1
break if other.max <= range.max # 沒有超過一個 range 的範圍
end
return MultiRange.new(new_ranges)
+ end
+
+ def |(other)
+ other_ranges = other.is_a?(MultiRange) ? other.ranges : [other]
+ return MultiRange.new(@ranges + other_ranges).flatten
+ end
+
+ def overlaps?(other)
+ multi_range = flatten
+ return multi_range.size != (multi_range - other).size
end
def sample
range = RouletteWheelSelection.sample(@ranges.map{|s| [s, s.size] }.to_h)
return nil if range == nil