class BetterRanges::SparseRange
Attributes
data[R]
Public Class Methods
new(*data)
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 5 def initialize(*data) @data = [*data].map! do |x| if x.is_a?(Enumerable) return nil if x.none? return x.data.clone if x.is_a?(SparseRange) end x end optimize end
Public Instance Methods
&(x)
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 87 def &(x) intersect = SparseRange.new intersect_data = intersect.data i = 0 next_val = lambda do throw :done unless i < @data.length v = read_val(@data[i]) i += 1 v end catch(:done) do other = (x.is_a?(SparseRange) ? x : SparseRange.new(x)).data start, finish = next_val.call other.each do |r| other_start, other_finish = read_val(r) start, finish = next_val.call while finish < other_start until other_finish < start first = [start, other_start].max last = [finish, other_finish].min intersect_data << write_val(first, last) start = last.succ if start < other_finish other_start = start start, finish = next_val.call end end end end intersect end
Also aliased as: intersect
-(x)
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 50 def -(x) diff = SparseRange.new diff_data = diff.data i = 0 next_val = lambda do throw :done unless i < @data.length v = read_val(@data[i]) i += 1 v end catch(:done) do other = (x.is_a?(SparseRange) ? x : SparseRange.new(x)).data start, finish = next_val.call other.each do |r| other_start, other_finish = read_val(r) while finish < other_start diff_data << write_val(start, finish) start, finish = next_val.call end next if other_finish < start diff_data << (start.succ == other_start ? start : (start...other_start)) if start < other_start start = other_finish.succ start, finish = next_val.call if start > finish end diff_data << write_val(start, finish) loop { diff_data << write_val(*next_val.call) } end diff end
Also aliased as: minus, difference
<<(x)
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 125 def <<(x) @data << [*(x.is_a?(SparseRange) ? x.data : x)] optimize self end
Also aliased as: add
==(x)
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 150 def ==(x) other = (x.is_a?(SparseRange) ? x : SparseRange.new(x)).data i = 0 (@data.length == other.length) && @data.all? do |e| o = other[i] i += 1 (e == o) || (read_val(e) == read_val(o)) end end
Also aliased as: eql?
each(&block)
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 16 def each(&block) Enumerator.new do |yielder| @data.each do |r| yield_each(r) { |x| yielder.yield x } end end.each(&block) end
empty?()
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 142 def empty? @data.empty? || size == 0 end
hash()
click to toggle source
TODO: Calculate hash without creating the temp array
# File lib/better_ranges/sparse_range.rb, line 161 def hash @data.map(&method(:read_val)).hash end
include?(x)
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 136 def include?(x) @data.any? do |r| r.is_a?(Range) ? r.include?(x) : x == r end end
inspect()
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 132 def inspect @data.inspect end
last()
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 42 def last read_val(@data.last).last end
size()
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 146 def size @data.reduce(0) { |a, e| a + (e.is_a?(Range) ? e.count : 1) } end
sparse_each(&block)
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 24 def sparse_each(&block) @data.each do |x| x.is_a?(Range) ? x : (x..x) end end
step(num = 1, &block)
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 30 def step(num = 1, &block) i = 0 Enumerator.new do |yielder| @data.each do |r| yield_each(r) do |x| yielder.yield x if (i % num) == 0 i += 1 end end end.each(&block) end
Protected Instance Methods
yield_each(e) { |x| ... }
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 183 def yield_each(e) if e.is_a?(Range) e.each { |x| yield x } else yield e end end
Private Instance Methods
optimize()
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 205 def optimize @data.flatten! @data.compact! @data.sort! { |a, b| (a <=> b) || (read_val(a) <=> read_val(b)) } fixed = [] start, finish = read_val(@data.first) for i in (1...@data.length) first, last = read_val(@data[i]) if finish.succ >= first finish = last if last > finish else fixed << write_val(start, finish) start, finish = first, last end end fixed << write_val(start, finish) if finish @data = fixed end
read_val(x)
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 193 def read_val(x) if x.is_a?(Range) [x.first, (x.exclude_end? ? x.max : x.last)] else [x, x] end end
write_val(start, finish)
click to toggle source
# File lib/better_ranges/sparse_range.rb, line 201 def write_val(start, finish) (start != finish ? (start..finish) : finish) end