From 9aaaf8b6c9832dcbebdf24fbf5720987a4ae80d2 Mon Sep 17 00:00:00 2001 From: Masatoshi SEKI Date: Wed, 14 Sep 2011 01:06:56 +0900 Subject: [PATCH] head_tag --- lib/drip.rb | 33 +++++++++++++++++++++++++++++++-- test/basic.rb | 32 +++++++++++++++++++++++++------- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/lib/drip.rb b/lib/drip.rb index b5c1030..0be72e4 100644 --- a/lib/drip.rb +++ b/lib/drip.rb @@ -8,6 +8,26 @@ class Drip def inspect; to_s; end class ImmutableDrip + class Generator + def initialize(pool=[], tag=[]) + @pool = pool + @tag = tag + end + + def add(key, value, *tag) + @pool << [key, value] + tag.uniq.each do |t| + @tag << [[t, key], value] + end + end + + def generate + ImmutableDrip.new(@pool.sort, @tag.sort) + end + end + + INF = 1.0/0 + def initialize(pool=[], tag=[]) @pool = pool @tag = tag @@ -35,6 +55,15 @@ def read_tag(key, tag, n=1) } end + def head_tag(n, tag) + lower = lower_boundary(@tag, [tag, 0]) + upper = upper_boundary(@tag, [tag, INF]) + lower = [lower, upper - n].max + @tag[lower ... upper].collect {|kv| + [kv[0][1], *kv[1].to_a] + } + end + def head(n=1, tag=nil) return head_tag(n, tag) if tag n = @pool.size < n ? @pool.size : n @@ -61,7 +90,7 @@ def lower_boundary(ary, key) upper = ary.size while lower + 1 != upper mid = (lower + upper).div(2) - if key > ary[mid][0] + if (ary[mid][0] <=> key) < 0 lower = mid else upper = mid @@ -75,7 +104,7 @@ def upper_boundary(ary, key) upper = ary.size while lower + 1 != upper mid = (lower + upper).div(2) - if key >= ary[mid][0] + if (ary[mid][0] <=> key) <= 0 lower = mid else upper = mid diff --git a/test/basic.rb b/test/basic.rb index d410e4a..aabe8e0 100644 --- a/test/basic.rb +++ b/test/basic.rb @@ -201,14 +201,19 @@ def test_bsearch assert_equal(8, im.upper_boundary(ary, 'g')) end + def add_to_gen(gen, key, value, *tag) + gen.add(key, [value, *tag], *tag) + end + def test_fetch_and_read_wo_tag - ary = [] - ary << [21, ['a']] - ary << [39, ['b']] - ary << [60, ['c', 'tag']] - ary << [99, ['d', 'tag']] - - im = Drip::ImmutableDrip.new(ary, []) + gen = Drip::ImmutableDrip::Generator.new + add_to_gen(gen, 21, 'a') + add_to_gen(gen, 99, 'd', 'tag') + add_to_gen(gen, 39, 'b') + add_to_gen(gen, 60, 'c', 'tag') + + im = gen.generate + assert_equal(nil, im.fetch(20)) assert_equal(['a'], im.fetch(21)) assert_equal(nil, im.fetch(23)) @@ -242,4 +247,17 @@ def test_fetch_and_read_wo_tag assert_equal([99, 'd', 'tag'], im.newer(60)) assert_equal(nil, im.newer(99)) end + + def test_read_w_tag + gen = Drip::ImmutableDrip::Generator.new + add_to_gen(gen, 21, 'a') + add_to_gen(gen, 39, 'b', 'b', 'tag') + add_to_gen(gen, 60, 'c', 'c', 'tag') + add_to_gen(gen, 99, 'd', 'tag', 'd') + add_to_gen(gen, 159, 'e', 'tag2', 'e') + im = gen.generate + + assert_equal([[99, 'd', 'tag', 'd']], im.head(1, 'tag')) + assert_equal([[99, 'd', 'tag', 'd']], im.head(1, 'd')) + end end