dskiplist 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 +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +14 -9
- data/dskiplist.gemspec +2 -0
- data/lib/dskiplist/version.rb +1 -1
- data/lib/dskiplist.rb +12 -10
- data/skiplist-test.rb +3 -3
- data/test/skiplist_spec.rb +20 -1
- data/test/time_spec.rb +0 -0
- metadata +33 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb6861be71eb077b906f12316726cb693ae766f1
|
4
|
+
data.tar.gz: 5ec1bb7f07a7936d02fa7d3635899c018f599fa3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eeb3eb32bfcca7b5e6b0577958178fdd42e1264de0ec21aecc634102132d2872e4b7a08bb975a683f2995f9723cdc25222725f2dca00b1d3a3f90792a18edc85
|
7
|
+
data.tar.gz: aee1b4ccc0bdaf0ca7f356894016599c70af9d40c883b963d075d0390efff88d69b91b7fa258858d7444b15e25daf9973fba01e7ea338baf8a59a1a05a30bb96
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
## DSkipList 1.0.0 (Feb 26, 2014) ##
|
2
|
+
|
3
|
+
* Changed all range operations so that they do not include the first element specified (from)
|
4
|
+
|
5
|
+
* Ranges now accept nonexistent start and endpoints and the list will still behave, which is more useful for
|
6
|
+
* real world situations in which you dont know exactly what values are in your list
|
7
|
+
|
data/README.md
CHANGED
@@ -97,24 +97,28 @@ Ok, so why use this instead of hash? Order
|
|
97
97
|
>> list.to_a
|
98
98
|
=> ["duck", "goose", "quail", "pidgin"]
|
99
99
|
|
100
|
-
#or in
|
100
|
+
#or in a range
|
101
101
|
>> from = 1
|
102
|
-
>>
|
102
|
+
>> through = 3
|
103
103
|
#0 is the base layer of the list. It contains all elements. default 0
|
104
104
|
>> layer = 0
|
105
105
|
#limit return size if desired
|
106
106
|
>> limit = nil
|
107
107
|
|
108
|
-
>> list.to_a(from,
|
109
|
-
=> ["duck", "goose", "quail"]
|
110
|
-
>> list.to_a(2, nil, 2)
|
108
|
+
>> list.to_a(from, through, limit, layer)
|
111
109
|
=> ["goose", "quail"]
|
110
|
+
#note that "duck" was omitted. The range does not include the first element.
|
111
|
+
#You can also use nonexistent node keys like 1.5
|
112
|
+
|
113
|
+
#with a start point, no endpoint, and a limit:
|
114
|
+
>> list.to_a(2, nil, 2)
|
115
|
+
=> ["quail", "pidgin"]
|
112
116
|
>> list.to_a(nil, 3, nil)
|
113
117
|
=> ["duck", "goose", "quail"]
|
114
118
|
|
115
|
-
#or count the elements between two
|
116
|
-
>> list.count(from,
|
117
|
-
=>
|
119
|
+
#or count the elements between two values (+1 because endpoint is counted) from 1 to 3
|
120
|
+
>> list.count(from, through)
|
121
|
+
=> 2
|
118
122
|
|
119
123
|
```
|
120
124
|
|
@@ -131,4 +135,5 @@ Ok, so why use this instead of hash? Order
|
|
131
135
|
|
132
136
|
ToDo:
|
133
137
|
- Jruby multithreading and locking with mutexes for multi-core support.
|
134
|
-
- Lazy operations
|
138
|
+
- Lazy operations. For now you can just do them yourself by using find_node to get your start point and calling forward[0] to get the following nodes in O(1) time
|
139
|
+
- considering making count O(1) instead of O(log n) by just keeping track of the size
|
data/dskiplist.gemspec
CHANGED
@@ -16,6 +16,8 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
|
+
spec.add_runtime_dependency "facter"
|
20
|
+
spec.add_runtime_dependency "thread_safe"
|
19
21
|
spec.add_development_dependency "rspec"
|
20
22
|
spec.add_development_dependency "bundler", "~> 1.5"
|
21
23
|
spec.add_development_dependency "rake"
|
data/lib/dskiplist/version.rb
CHANGED
data/lib/dskiplist.rb
CHANGED
@@ -36,6 +36,7 @@ class DSkipList
|
|
36
36
|
@key = k
|
37
37
|
@value = v.nil? ? k : v
|
38
38
|
@forward = []
|
39
|
+
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
@@ -62,10 +63,10 @@ class DSkipList
|
|
62
63
|
x = x.forward[i]
|
63
64
|
end
|
64
65
|
end
|
65
|
-
x = x.forward[0] if x.forward[0].key == search_key
|
66
|
+
x = x.forward[0] if x.forward[0] and x.forward[0].key == search_key
|
66
67
|
return x
|
67
68
|
end
|
68
|
-
|
69
|
+
|
69
70
|
def [] key
|
70
71
|
node = self.find_node(key)
|
71
72
|
if node and node.key == key
|
@@ -144,10 +145,11 @@ class DSkipList
|
|
144
145
|
end
|
145
146
|
|
146
147
|
def count(from = nil, to = nil, level = 0)
|
147
|
-
|
148
|
+
each(from, to, nil, level, nil)
|
148
149
|
end
|
149
150
|
|
150
|
-
|
151
|
+
#accepts a block which is run on each element
|
152
|
+
def each(from=nil, to=nil, limit=nil, level=0, output=nil)
|
151
153
|
if from
|
152
154
|
x = find_node(from)
|
153
155
|
x = x.forward[level] if x.forward[level]
|
@@ -182,11 +184,11 @@ class DSkipList
|
|
182
184
|
end
|
183
185
|
|
184
186
|
def to_h(from = nil, to = nil, limit = nil, level = 0)
|
185
|
-
|
187
|
+
each(from, to, limit, level, {}) {|n, hash| hash[n.key] = n.value}
|
186
188
|
end
|
187
189
|
|
188
190
|
def to_a(from = nil, to = nil, limit = nil, level = 0)
|
189
|
-
|
191
|
+
each(from, to, limit, level, []) {|n, arr| arr.push(n.value)}
|
190
192
|
end
|
191
193
|
alias_method :to_ary, :to_a
|
192
194
|
|
@@ -216,9 +218,9 @@ class DSkipList
|
|
216
218
|
return "SkipList level #{@max_level}"
|
217
219
|
end
|
218
220
|
|
219
|
-
def each(&block)
|
220
|
-
|
221
|
-
|
221
|
+
#def each(&block)
|
222
|
+
# self.walk(nil, nil, nil, 0, nil) @block
|
223
|
+
# return self
|
224
|
+
#end
|
222
225
|
|
223
226
|
end
|
224
|
-
|
data/skiplist-test.rb
CHANGED
@@ -5,13 +5,13 @@ list = DSkipList.new
|
|
5
5
|
otherList = SkipList.new 100
|
6
6
|
hash = {}
|
7
7
|
Benchmark.bm(30) do |b|
|
8
|
-
|
8
|
+
b.report('Insert time: ') {1.upto(10000) {|i| list[i] = i}}
|
9
9
|
#b.report('Other list insert: ') {1.upto(10000) {|i| otherList[i] = i}}
|
10
|
-
|
10
|
+
b.report('Search time: ') {1.upto(10000) {|i| list[i]}}
|
11
11
|
#b.report('Other list search: ') {1.upto(10000) {|i| otherList[i]}}
|
12
12
|
#b.report('List insert million elements: ') {10000.upto(1010000) {|i| list[i] = i}}
|
13
13
|
#b.report('Hash insert million elements: ') {1.upto(1000000) {|i| hash[i] = i}}
|
14
|
-
|
14
|
+
b.report('List search 10000') {1.upto(10000) {|i| list[i]}}
|
15
15
|
#b.report('Hash search 10000') {900000.upto(1000000) {|i| hash[i]}}
|
16
16
|
#b.report('List +10000: ') {1040000.upto(1050000) {|i| list[i] = i}}
|
17
17
|
#b.report('Search time: ') {1000000.upto(1010000) {|i| list[i]}}
|
data/test/skiplist_spec.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
+
#Be sure to run 'gem install dskiplist --development' before running
|
2
|
+
#require 'method_profiler'
|
1
3
|
require 'rspec'
|
2
4
|
require './lib/dskiplist.rb'
|
3
5
|
require 'pry'
|
6
|
+
|
4
7
|
#Checks for stray links in the upper levels. There may be a more exhaustive way to check integrity.
|
5
8
|
def check_integrity(list)
|
6
9
|
complete = list.to_a
|
@@ -22,8 +25,11 @@ describe "The skiplist" do
|
|
22
25
|
check_integrity(@list)
|
23
26
|
end
|
24
27
|
|
28
|
+
it "sets up the observer", :time => true do
|
29
|
+
#@profiler = MethodProfiler.observe(@list)
|
30
|
+
end
|
31
|
+
|
25
32
|
it "should lookup value correctly" do
|
26
|
-
puts "30 returned #{@list[30]}"
|
27
33
|
expect(@list[30]).to eq(30)
|
28
34
|
end
|
29
35
|
|
@@ -48,6 +54,9 @@ describe "The skiplist" do
|
|
48
54
|
end
|
49
55
|
end
|
50
56
|
|
57
|
+
it "should return nil if key not found" do
|
58
|
+
expect(@list[99999999989].nil?).to eq(true)
|
59
|
+
end
|
51
60
|
it "should convert to hash" do
|
52
61
|
expect(@list.to_h.count).to eq(100)
|
53
62
|
expect(@list.to_h(50,75).count).to eq(25)
|
@@ -68,4 +77,14 @@ describe "The skiplist" do
|
|
68
77
|
#check sizes of each level to make sure we aren't chopping off the tail when we delete. Seems fine
|
69
78
|
#@list.level.downto(0) {|l| puts "level #{l} contains #{@list.count(nil, nil, l)}"}
|
70
79
|
end
|
80
|
+
|
81
|
+
it "should accept a block" do
|
82
|
+
object_count = 0
|
83
|
+
@list.each { object_count +=1 }
|
84
|
+
expect(object_count).to eq(100)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "reports the observer", :time => true do
|
88
|
+
#puts @profiler.report
|
89
|
+
end
|
71
90
|
end
|
data/test/time_spec.rb
ADDED
File without changes
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dskiplist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Forrest Allison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02
|
11
|
+
date: 2014-03-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: facter
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thread_safe
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: rspec
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,6 +123,7 @@ files:
|
|
95
123
|
- ".git-new/objects/ae/ee3428c017916e5cc0e57d387224f33ed0b990"
|
96
124
|
- ".git-new/objects/d8/7d4be66f458acd52878902bbf1391732ad21e1"
|
97
125
|
- ".gitignore"
|
126
|
+
- CHANGELOG.md
|
98
127
|
- Gemfile
|
99
128
|
- LICENSE.txt
|
100
129
|
- README.md
|
@@ -105,6 +134,7 @@ files:
|
|
105
134
|
- lib/dskiplist/version.rb
|
106
135
|
- skiplist-test.rb
|
107
136
|
- test/skiplist_spec.rb
|
137
|
+
- test/time_spec.rb
|
108
138
|
homepage: https://github.com/light24bulbs/dynamic-skiplist/
|
109
139
|
licenses:
|
110
140
|
- MIT
|
@@ -131,3 +161,4 @@ specification_version: 4
|
|
131
161
|
summary: High speed skiplist gem
|
132
162
|
test_files:
|
133
163
|
- test/skiplist_spec.rb
|
164
|
+
- test/time_spec.rb
|