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