Skip to content

Commit 119cd81

Browse files
committed
Added SortedSet#between
1 parent 2845372 commit 119cd81

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

lib/hamster/sorted_set.rb

+34
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,14 @@ def up_to(item, &block)
560560
end
561561
end
562562

563+
def between(from, to, &block)
564+
if block_given?
565+
@node.each_between(from, to, @comparator, &block)
566+
else
567+
self.class.alloc(@node.between(from, to, @comparator), @comparator)
568+
end
569+
end
570+
563571
# Return a randomly chosen item from this set. If the set is empty, return `nil`.
564572
#
565573
# @return [Object]
@@ -778,6 +786,18 @@ def suffix(item, comparator, inclusive)
778786
end
779787
end
780788

789+
def between(from, to, comparator)
790+
if direction(from, comparator) > 0 # all on the right
791+
@right.between(from, to, comparator)
792+
elsif direction(to, comparator) < 0 # all on the left
793+
@left.between(from, to, comparator)
794+
else
795+
left = @left.suffix(from, comparator, true)
796+
right = @right.prefix(to, comparator, true)
797+
rebalance(left, right)
798+
end
799+
end
800+
781801
def each_less(item, comparator, inclusive, &block)
782802
dir = direction(item, comparator)
783803
if dir > 0 || (inclusive && dir == 0)
@@ -800,6 +820,18 @@ def each_greater(item, comparator, inclusive, &block)
800820
end
801821
end
802822

823+
def each_between(from, to, comparator, &block)
824+
if direction(from, comparator) > 0 # all on the right
825+
@right.each_between(from, to, comparator, &block)
826+
elsif direction(to, comparator) < 0 # all on the left
827+
@left.each_between(from, to, comparator, &block)
828+
else
829+
@left.each_greater(from, comparator, true, &block)
830+
yield @item
831+
@right.each_less(to, comparator, true, &block)
832+
end
833+
end
834+
803835
def each(&block)
804836
@left.each(&block)
805837
yield @item
@@ -942,8 +974,10 @@ def e.delete(item, comparator); self; end
942974
def e.include?(item, comparator); false; end
943975
def e.prefix(item, comparator, inclusive); self; end
944976
def e.suffix(item, comparator, inclusive); self; end
977+
def e.between(from, to, comparator); self; end
945978
def e.each_greater(item, comparator, inclusive); end
946979
def e.each_less(item, comparator, inclusive); end
980+
def e.each_between(item, comparator, inclusive); end
947981
def e.empty?; true; end
948982
def e.slice(from, length); self; end
949983
end.freeze
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
require "spec_helper"
2+
require "hamster/sorted_set"
3+
4+
describe Hamster::SortedSet do
5+
describe "#between" do
6+
context "when called without a block" do
7+
it "returns a sorted set of all items from the first argument to the second" do
8+
100.times do
9+
items = rand(100).times.collect { rand(1000) }
10+
set = Hamster::SortedSet.new(items)
11+
from,to = [rand(1000),rand(1000)].sort
12+
result = set.between(from, to)
13+
array = items.select { |x| x >= from && x <= to }.sort
14+
result.class.should be(Hamster::SortedSet)
15+
result.size.should == array.size
16+
result.to_a.should == array
17+
end
18+
end
19+
end
20+
21+
context "when called with a block" do
22+
it "yields all the items lower than the argument" do
23+
100.times do
24+
items = rand(100).times.collect { rand(1000) }
25+
set = Hamster::SortedSet.new(items)
26+
from,to = [rand(1000),rand(1000)].sort
27+
result = []
28+
set.between(from, to) { |x| result << x }
29+
array = items.select { |x| x >= from && x <= to }.sort
30+
result.size.should == array.size
31+
result.should == array
32+
end
33+
end
34+
end
35+
36+
context "on an empty set" do
37+
it "returns an empty set" do
38+
Hamster::SortedSet.empty.between(1, 2).should be_empty
39+
Hamster::SortedSet.empty.between('abc', 'def').should be_empty
40+
Hamster::SortedSet.empty.between(:symbol, :another).should be_empty
41+
end
42+
end
43+
44+
context "with a 'to' argument lower than the 'from' argument" do
45+
it "returns an empty set" do
46+
result = Hamster.sorted_set(*(1..100)).between(6, 5)
47+
result.class.should be(Hamster::SortedSet)
48+
result.should be_empty
49+
end
50+
end
51+
end
52+
end

0 commit comments

Comments
 (0)