top_n 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a5fc5435e211281c5d59fa26d155260a0359a216
4
- data.tar.gz: f3cd1bf16b9c9c11ad87793a7c0741e1fe7f314a
3
+ metadata.gz: cda9c5805aaeda70a3ea35e8a01314a96e071cd5
4
+ data.tar.gz: f581488f6929408afe40e98567b076fc1d09f42f
5
5
  SHA512:
6
- metadata.gz: 471670b61a3b91ff867fab94bcd414a9f766fb7367579122ea57d5f4d58e7b964e4551d77bb4ce35a4b2523df7282dce8a845791c0c8c7677ff4ec46c82b4071
7
- data.tar.gz: 24330b140e01c80493d4434720672bef428825bbb8a6133ab234443c77bf498583f4c91360e2a33524da9d4e02a20814ec450a33ed14498a3dbe1c6b435eb08b
6
+ metadata.gz: f55b87b0711b17b8fee03294baffa347c1df8fb92f010198418870ed5a337a2559358e76cd4a92ded26c424da9e9a9abfea7ef9bea9c744723a3cd3a62b8d2b4
7
+ data.tar.gz: dab46fa2befd85a4edc51c5c7bef1f4f41b43e1e57ee2aaae0ff5031cf1a0e6fb458f58261e6ca7b20dd5de288edd6bf625d57acc5f0bc942d5a06249f6e19e3
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0
1
+ 1.0.1
@@ -66,6 +66,12 @@ class TopN
66
66
  direction: :top,
67
67
  }.merge(options)
68
68
 
69
+ options.keys.each do |opt|
70
+ unless [:maxsize, :direction].include?opt
71
+ raise ArgumentError.new("invalid option #{opt}")
72
+ end
73
+ end
74
+
69
75
  @maxsize = options[:maxsize]
70
76
  @direction = options[:direction]
71
77
  @data = {}
@@ -137,20 +143,20 @@ class TopN
137
143
  def add_top(key, value)
138
144
  @threshold_key ||= key
139
145
 
140
- if @size >= @maxsize
141
- return nil if key < @threshold_key
142
- @data.delete(@threshold_key)
143
- end
144
-
145
- unless @data.has_key?key
146
- @data[key] = []
147
- @size += 1 if @size < @maxsize
146
+ if @data.has_key?key
147
+ @data[key] << value
148
+ else
149
+ if @size >= @maxsize
150
+ return nil if key < @threshold_key
151
+ @data.delete(@threshold_key)
152
+ @size -= 1
153
+ @threshold_key = @data.keys.min
154
+ end
155
+ @data[key] = [ value ]
156
+ @size += 1
157
+ @threshold_key = key if key < @threshold_key
148
158
  end
149
159
 
150
- @data[key] << value
151
-
152
- @threshold_key = key if key < @threshold_key
153
-
154
160
  @data[key]
155
161
  end
156
162
 
@@ -159,20 +165,20 @@ class TopN
159
165
  def add_bottom(key, value)
160
166
  @threshold_key ||= key
161
167
 
162
- if @size >= @maxsize
163
- return nil if key > @threshold_key
164
- @data.delete(@threshold_key)
165
- end
166
-
167
- unless @data.has_key?key
168
- @data[key] = []
169
- @size += 1 if @size < @maxsize
168
+ if @data.has_key?key
169
+ @data[key] << value
170
+ else
171
+ if @size >= @maxsize
172
+ return nil if key > @threshold_key
173
+ @data.delete(@threshold_key)
174
+ @size -= 1
175
+ @threshold_key = @data.keys.max
176
+ end
177
+ @data[key] = [ value ]
178
+ @size += 1
179
+ @threshold_key = key if key > @threshold_key
170
180
  end
171
181
 
172
- @data[key] << value
173
-
174
- @threshold_key = key if key > @threshold_key
175
-
176
182
  @data[key]
177
183
  end
178
184
  end
@@ -85,4 +85,19 @@ class TestAddingBottom < Minitest::Test
85
85
  assert_equal [2], topn.find(2)
86
86
  assert_nil topn.find(3)
87
87
  end
88
+
89
+ def test_torture
90
+ topn = TopN.new(direction: :bottom, maxsize: 10)
91
+
92
+ records = []
93
+ 300_000.times do
94
+ record = rand(4000)
95
+ records << record
96
+ topn.add(record, rand(100_000_000))
97
+ end
98
+
99
+ top_records = records.uniq.sort[0..9]
100
+ keys = topn.keys.sort
101
+ assert_equal top_records, keys
102
+ end
88
103
  end
@@ -85,4 +85,19 @@ class TestAddingTop < Minitest::Test
85
85
  assert_equal [2], topn.find(2)
86
86
  assert_equal [3], topn.find(3)
87
87
  end
88
+
89
+ def test_torture
90
+ topn = TopN.new(maxsize: 1000)
91
+
92
+ records = []
93
+ 300_000.times do
94
+ record = rand(4000)
95
+ records << record
96
+ topn.add(record, rand(100_000_000))
97
+ end
98
+
99
+ top_records = records.uniq.sort { |a, b| b <=> a }[0..999]
100
+ keys = topn.keys.sort { |a, b| b <=> a }
101
+ assert_equal top_records, keys
102
+ end
88
103
  end
@@ -44,4 +44,10 @@ class TestTopN < Minitest::Test
44
44
  TopN.new(maxsize: 'foo')
45
45
  }
46
46
  end
47
+
48
+ def test_creation_raises_assertion_for_invalid_argument_names
49
+ assert_raises(ArgumentError) {
50
+ TopN.new(flarg: 1)
51
+ }
52
+ end
47
53
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "top_n"
8
- s.version = "1.0.0"
8
+ s.version = "1.0.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Michael Graff"]
12
- s.date = "2013-12-15"
12
+ s.date = "2013-12-16"
13
13
  s.description = "Track the top (or bottom) N keys added to a list, and discard the remainder."
14
14
  s.email = "explorer@flame.org"
15
15
  s.extra_rdoc_files = [
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: top_n
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Graff
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-15 00:00:00.000000000 Z
11
+ date: 2013-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest