skn_utils 3.3.5 → 3.3.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +37 -5
- data/lib/skn_utils/lists/circular_linked_list.rb +8 -163
- data/lib/skn_utils/lists/doubly_linked_list.rb +18 -180
- data/lib/skn_utils/lists/link_node.rb +37 -1
- data/lib/skn_utils/lists/linked_commons.rb +202 -0
- data/lib/skn_utils/lists/linked_list.rb +19 -183
- data/lib/skn_utils/version.rb +1 -1
- data/lib/skn_utils.rb +1 -0
- data/spec/lib/skn_utils/lists/node_based_linked_list_spec.rb +85 -0
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fd1ca93fc5fbcbdf6d22f5c45851fcd36e19e88
|
4
|
+
data.tar.gz: 0aeaade9f44e5a69c701946d24542c9c88f2995e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a934d2d35f6680f15b923df769e3da95795d122317fe15bb49b26aa5917b077c7fa81040b02ef637a26d4bef15791cc447538c663c187b83681e5c698dc6627
|
7
|
+
data.tar.gz: a05eae70e269463828a96e6c8e714cd214bacb5bf1256caee2220cdf1c62d634bc58a61e7f42f556e08c2a4254ae27547149186cbf3cd632b85ca871b1c6b1da
|
data/README.md
CHANGED
@@ -17,8 +17,8 @@ Ruby Gem containing a Ruby PORO (Plain Old Ruby Object) that can be instantiated
|
|
17
17
|
|
18
18
|
## New Features
|
19
19
|
08/2017 V3.3.0
|
20
|
-
Added Linked List classes which implement
|
21
|
-
|
20
|
+
Added Linked List classes which implement Single, Double, and Circular linked lists patterns. LinkedLists are implemented
|
21
|
+
with method results returning node values or the nodes themselves.
|
22
22
|
|
23
23
|
07/2017 V3.1.5
|
24
24
|
Added SknSettings class for use as a replacement to the popular, but obsolete, Config.gem
|
@@ -70,9 +70,13 @@ Ruby Gem containing a Ruby PORO (Plain Old Ruby Object) that can be instantiated
|
|
70
70
|
|
71
71
|
|
72
72
|
## Public Methods: SknUtils::Lists::LinkedList, SknUtils::Lists::DoublyLinkedList, and SknUtils::Lists::CircularLinkedList
|
73
|
-
|
74
|
-
|
73
|
+
#### Each concrete Class supports the following methods: Value based interface
|
74
|
+
Value based interface presumes a direct reference to the object is maintained and the following methods will be called on that
|
75
|
+
object instance as needed. Each method will generally return the value contained in the node, Nil, or the int number of nodes
|
76
|
+
remaining.
|
77
|
+
|
75
78
|
Navigation: return related value from relative positon in list, stops on first/last node for Single/Double, wraps for Circular.
|
79
|
+
|
76
80
|
#first -- returns first value in list
|
77
81
|
#next -- returns next value from current position
|
78
82
|
#current -- returns current value
|
@@ -94,6 +98,7 @@ Ruby Gem containing a Ruby PORO (Plain Old Ruby Object) that can be instantiated
|
|
94
98
|
block format is: {|a,b| a >= b }; example: 'll.sort(:default) {|a,b| a <= b}'
|
95
99
|
|
96
100
|
Modification: returns number of elements in the list after the operation
|
101
|
+
|
97
102
|
#insert(value) -- inserts value after node at current positon, or appends
|
98
103
|
#append(value) -- inserts value after node at current positon
|
99
104
|
#prepend(value) -- inserts value before node at current positon
|
@@ -102,9 +107,36 @@ Ruby Gem containing a Ruby PORO (Plain Old Ruby Object) that can be instantiated
|
|
102
107
|
#remove(value) -- finds first node matching value, then destroys it
|
103
108
|
|
104
109
|
Initialization: optional &block to identify data key
|
110
|
+
|
105
111
|
#new(*vargs, &block) -- Instansiates new list and optionally creates nodes from each comma-seperated value;
|
106
112
|
also, assigns &block as default value identifier for find and sort operations
|
107
|
-
|
113
|
+
returns a class instance.
|
114
|
+
compare_key_block example: instance = LinkedList.new({:key=>"Z"},{:key=>"S"},{:key=>"N"}) {|a| a[:key]}
|
115
|
+
|
116
|
+
#### Each concrete Class supports the following methods: Node based interface
|
117
|
+
Node based interface presumes a node is retrieved from the LinkedList, then using that/any available node all other methods
|
118
|
+
may be used. Methods in play will include the LinkedNode (#next, #value, and #prev), along with all public methods from
|
119
|
+
the main class.
|
120
|
+
|
121
|
+
Navigation: return related Node from relative positon in list, stops on first/last node for Single/Double, wraps for Circular.
|
122
|
+
|
123
|
+
#first_node -- returns first node
|
124
|
+
#next_node -- returns next node from current position
|
125
|
+
#current_node -- returns current or last accessed node
|
126
|
+
#prev_node -- returns previous node from current position (*not supported in Single)
|
127
|
+
#last_node -- returns last node in list
|
128
|
+
#node_value -- returns value of the current/receiver node: $ receiver.node_value
|
129
|
+
#node_request(method_sym, *vargs, &block)
|
130
|
+
-- executes any method on the Value based Interface, returning a node
|
131
|
+
#node_value_request(method_sym, *vargs, &block)
|
132
|
+
-- executes any method on the Value based Interface, returning result value
|
133
|
+
|
134
|
+
Initialization: optional &block to identify data key
|
135
|
+
|
136
|
+
#call(*vargs, &block) -- Instansiates new list and optionally creates nodes from each comma-seperated value;
|
137
|
+
also, assigns &block as default value identifier for find and sort operations
|
138
|
+
returns the first node when initialized with vargs -- else class instance
|
139
|
+
compare_key_block example: node = LinkedList.call({:key=>"Z"},{:key=>"S"},{:key=>"N"}) {|a| a[:key]}
|
108
140
|
|
109
141
|
|
110
142
|
## Public Methods: SknSettings ONLY
|
@@ -27,54 +27,24 @@ module SknUtils
|
|
27
27
|
# Circularly Linked List
|
28
28
|
# Forward (#next) and Backwards (#prev) navigation
|
29
29
|
# No Head or Tail
|
30
|
-
class CircularLinkedList
|
31
|
-
attr_accessor :size
|
32
30
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
@match_value = block_given? ? compare_key_proc : lambda {|obj| obj }
|
40
|
-
@sort_ascending = lambda {|a_obj,b_obj| @match_value.call(a_obj) >= @match_value.call(b_obj)}
|
41
|
-
@sort_descending = lambda {|a_obj,b_obj| @match_value.call(a_obj) <= @match_value.call(b_obj)}
|
42
|
-
@sort_condition = @sort_ascending
|
43
|
-
|
44
|
-
vargs.each {|value| insert(value) }
|
45
|
-
first if vargs.size > 1
|
46
|
-
end
|
31
|
+
# LinkedCommons provides;
|
32
|
+
# - #initialize, #first, #next, #current, #last, #at_index,
|
33
|
+
# #insert, #prepend, #append, #empty?, #clear,
|
34
|
+
# #each, #to_a, and #sort!
|
35
|
+
#
|
36
|
+
class CircularLinkedList < LinkedCommons
|
47
37
|
|
48
38
|
#
|
49
39
|
# Navigation
|
50
40
|
#
|
51
41
|
|
52
|
-
# return values and position current to last node accessed
|
53
|
-
# prevent @current from nil assignment
|
54
|
-
def first
|
55
|
-
@current = self.head if self.head
|
56
|
-
@current.value rescue nil
|
57
|
-
end
|
58
|
-
|
59
|
-
def next
|
60
|
-
@current = @current.next if @current and @current.next
|
61
|
-
@current.value rescue nil
|
62
|
-
end
|
63
|
-
|
64
|
-
def current
|
65
|
-
@current.value rescue nil
|
66
|
-
end
|
67
42
|
|
68
43
|
def prev
|
69
44
|
@current = @current.prev if @current and @current.prev
|
70
45
|
@current.value rescue nil
|
71
46
|
end
|
72
47
|
|
73
|
-
def last
|
74
|
-
@current = self.tail if self.tail
|
75
|
-
@current.value rescue nil
|
76
|
-
end
|
77
|
-
|
78
48
|
# -+ int position from current node
|
79
49
|
def nth(index)
|
80
50
|
node = @current
|
@@ -97,41 +67,14 @@ module SknUtils
|
|
97
67
|
current
|
98
68
|
end
|
99
69
|
|
100
|
-
# return node at positive index from head
|
101
|
-
def at_index(index)
|
102
|
-
find_by_index(index)
|
103
|
-
current
|
104
|
-
end
|
105
|
-
|
106
|
-
def empty?
|
107
|
-
self.size == 0
|
108
|
-
end
|
109
|
-
|
110
70
|
#
|
111
71
|
# Modifications
|
112
72
|
#
|
113
73
|
|
114
|
-
# return new size
|
115
|
-
def insert(value)
|
116
|
-
temp = @current.value rescue nil
|
117
|
-
insert_after(temp, value)
|
118
|
-
end
|
119
|
-
|
120
|
-
# return new size
|
121
|
-
def prepend(value)
|
122
|
-
temp = self.head.value rescue nil
|
123
|
-
insert_before(temp, value)
|
124
|
-
end
|
125
|
-
# return new size
|
126
|
-
def append(value)
|
127
|
-
temp = self.tail.value rescue nil
|
128
|
-
insert_after(temp, value)
|
129
|
-
end
|
130
|
-
|
131
74
|
# return new size
|
132
75
|
def insert_before(position_value, value)
|
133
76
|
target = find_by_value(position_value)
|
134
|
-
node = LinkNode.new(value, target, :circle_before, &@match_value)
|
77
|
+
node = LinkNode.new(value, target, :circle_before, self, &@match_value)
|
135
78
|
@current = node
|
136
79
|
if self.size == 0 # only
|
137
80
|
self.head = node
|
@@ -151,7 +94,7 @@ module SknUtils
|
|
151
94
|
# return new size
|
152
95
|
def insert_after(position_value, value)
|
153
96
|
target = find_by_value(position_value)
|
154
|
-
node = LinkNode.new(value, target, :circle_after, &@match_value)
|
97
|
+
node = LinkNode.new(value, target, :circle_after, self, &@match_value)
|
155
98
|
@current = node
|
156
99
|
if self.size == 0 # only
|
157
100
|
self.head = node
|
@@ -197,83 +140,8 @@ module SknUtils
|
|
197
140
|
end
|
198
141
|
|
199
142
|
|
200
|
-
# return number cleared
|
201
|
-
def clear
|
202
|
-
rc = 0
|
203
|
-
node = self.head
|
204
|
-
position = node
|
205
|
-
while node do
|
206
|
-
node = node.remove!
|
207
|
-
rc += 1
|
208
|
-
break if position.equal?(node)
|
209
|
-
end
|
210
|
-
|
211
|
-
@current = nil
|
212
|
-
self.head = nil
|
213
|
-
self.tail = nil
|
214
|
-
self.size = 0
|
215
|
-
rc
|
216
|
-
end
|
217
|
-
|
218
|
-
#
|
219
|
-
# Enumerate
|
220
|
-
#
|
221
|
-
|
222
|
-
# perform each() or return enumerator
|
223
|
-
def each(&block)
|
224
|
-
@current = self.head
|
225
|
-
position = self.head
|
226
|
-
if block_given?
|
227
|
-
while position do
|
228
|
-
block.call( position.value.dup )
|
229
|
-
position = position.next
|
230
|
-
break if position === @current
|
231
|
-
end
|
232
|
-
else
|
233
|
-
Enumerator.new do |yielder|
|
234
|
-
while position do
|
235
|
-
yielder << position.value.dup
|
236
|
-
position = position.next
|
237
|
-
break if position === @current
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
# convert self to a value array
|
244
|
-
def to_a
|
245
|
-
@current = self.head
|
246
|
-
position = self.head
|
247
|
-
result = []
|
248
|
-
while position do
|
249
|
-
result << position.value.dup
|
250
|
-
position = position.next
|
251
|
-
break if position.equal?(@current)
|
252
|
-
end
|
253
|
-
result
|
254
|
-
end
|
255
|
-
|
256
|
-
# block format: sort condition : {|a_obj,b_obj| a_obj >= b_obj}
|
257
|
-
def sort!(direction_sym=:default, &compare_sort_proc)
|
258
|
-
@active_sort_condition = block_given? ? compare_sort_proc :
|
259
|
-
case direction_sym
|
260
|
-
when :asc
|
261
|
-
@sort_ascending
|
262
|
-
when :desc
|
263
|
-
@sort_descending
|
264
|
-
else
|
265
|
-
@sort_condition
|
266
|
-
end
|
267
|
-
sorted = merge_sort(self.to_a)
|
268
|
-
clear
|
269
|
-
sorted.each {|item| insert(item) }
|
270
|
-
self.size
|
271
|
-
end
|
272
|
-
|
273
143
|
protected
|
274
144
|
|
275
|
-
attr_accessor :head, :tail
|
276
|
-
|
277
145
|
def find_by_value(value)
|
278
146
|
return nil if value.nil? || self.size == 0
|
279
147
|
stop_node = self.head
|
@@ -295,29 +163,6 @@ module SknUtils
|
|
295
163
|
node
|
296
164
|
end
|
297
165
|
|
298
|
-
# Merged Sort via Ref: http://rubyalgorithms.com/merge_sort.html
|
299
|
-
# arr is Array to be sorted, sort_cond is Proc expecting a/b params returning true/false
|
300
|
-
def merge_sort(arr)
|
301
|
-
return arr if arr.size < 2
|
302
|
-
middle = arr.size / 2
|
303
|
-
left = merge_sort(arr[0...middle])
|
304
|
-
right = merge_sort(arr[middle..arr.size])
|
305
|
-
merge(left, right)
|
306
|
-
end
|
307
|
-
|
308
|
-
def merge(left, right)
|
309
|
-
sorted = []
|
310
|
-
while left.any? && right.any?
|
311
|
-
if @active_sort_condition.call(left.first, right.first)
|
312
|
-
sorted.push right.shift
|
313
|
-
else
|
314
|
-
sorted.push left.shift
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
|
-
sorted + left + right
|
319
|
-
end
|
320
|
-
|
321
166
|
end # end class
|
322
167
|
end # module
|
323
168
|
end # end module
|
@@ -28,54 +28,23 @@ module SknUtils
|
|
28
28
|
# Forward (#next) and Backwards (#prev) navigation
|
29
29
|
# Head when (prev == nil)
|
30
30
|
# Tail when (next == nil)
|
31
|
-
class DoublyLinkedList
|
32
|
-
attr_accessor :size
|
33
31
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
@match_value = block_given? ? compare_key_proc : lambda {|obj| obj }
|
41
|
-
@sort_ascending = lambda {|a_obj,b_obj| @match_value.call(a_obj) >= @match_value.call(b_obj)}
|
42
|
-
@sort_descending = lambda {|a_obj,b_obj| @match_value.call(a_obj) <= @match_value.call(b_obj)}
|
43
|
-
@sort_condition = @sort_ascending
|
44
|
-
|
45
|
-
vargs.each {|value| insert(value) }
|
46
|
-
first if vargs.size > 1
|
47
|
-
end
|
32
|
+
# LinkedCommons provides;
|
33
|
+
# - #initialize, #first, #next, #current, #last, #at_index,
|
34
|
+
# #insert, #prepend, #append, #empty?, #clear,
|
35
|
+
# #each, #to_a, and #sort!
|
36
|
+
#
|
37
|
+
class DoublyLinkedList < LinkedCommons
|
48
38
|
|
49
39
|
#
|
50
40
|
# Navigation
|
51
41
|
#
|
52
42
|
|
53
|
-
# return values and position current to last node accessed
|
54
|
-
# prevent @current from nil assignment
|
55
|
-
def first
|
56
|
-
@current = head if head
|
57
|
-
@current.value rescue nil
|
58
|
-
end
|
59
|
-
|
60
|
-
def next
|
61
|
-
@current = @current.next if @current and @current.next
|
62
|
-
@current.value rescue nil
|
63
|
-
end
|
64
|
-
|
65
|
-
def current
|
66
|
-
@current.value rescue nil
|
67
|
-
end
|
68
|
-
|
69
43
|
def prev
|
70
44
|
@current = @current.prev if @current and @current.prev
|
71
45
|
@current.value rescue nil
|
72
46
|
end
|
73
47
|
|
74
|
-
def last
|
75
|
-
@current = tail if tail
|
76
|
-
@current.value rescue nil
|
77
|
-
end
|
78
|
-
|
79
48
|
# -+ int position from current node
|
80
49
|
def nth(index)
|
81
50
|
node = @current
|
@@ -95,54 +64,27 @@ module SknUtils
|
|
95
64
|
current
|
96
65
|
end
|
97
66
|
|
98
|
-
# return node at positive index from head
|
99
|
-
def at_index(index)
|
100
|
-
find_by_index(index)
|
101
|
-
current
|
102
|
-
end
|
103
|
-
|
104
|
-
def empty?
|
105
|
-
size == 0
|
106
|
-
end
|
107
|
-
|
108
67
|
#
|
109
68
|
# Modifications
|
110
69
|
#
|
111
70
|
|
112
|
-
# return new size
|
113
|
-
def insert(value)
|
114
|
-
temp = @current.value rescue nil
|
115
|
-
insert_after(temp, value)
|
116
|
-
end
|
117
|
-
|
118
|
-
# return new size
|
119
|
-
def prepend(value)
|
120
|
-
temp = head.value rescue nil
|
121
|
-
insert_before(temp, value)
|
122
|
-
end
|
123
|
-
# return new size
|
124
|
-
def append(value)
|
125
|
-
temp = tail.value rescue nil
|
126
|
-
insert_after(temp, value)
|
127
|
-
end
|
128
|
-
|
129
71
|
# return new size
|
130
72
|
def insert_before(position_value, value)
|
131
73
|
target = find_by_value(position_value)
|
132
|
-
node = LinkNode.new(value, target, :before, &@match_value)
|
74
|
+
node = LinkNode.new(value, target, :before, self, &@match_value)
|
133
75
|
@current = node if target
|
134
|
-
self.head = node if head === target
|
135
|
-
self.tail = node if tail.nil?
|
76
|
+
self.head = node if self.head === target
|
77
|
+
self.tail = node if self.tail.nil?
|
136
78
|
self.size += 1
|
137
79
|
end
|
138
80
|
|
139
81
|
# return new size
|
140
82
|
def insert_after(position_value, value)
|
141
83
|
target = find_by_value(position_value)
|
142
|
-
node = LinkNode.new(value, target, :after, &@match_value)
|
84
|
+
node = LinkNode.new(value, target, :after, self, &@match_value)
|
143
85
|
@current = node
|
144
|
-
self.head = node if head.nil?
|
145
|
-
self.tail = node if tail === target
|
86
|
+
self.head = node if self.head.nil?
|
87
|
+
self.tail = node if self.tail === target
|
146
88
|
self.size += 1
|
147
89
|
end
|
148
90
|
|
@@ -150,7 +92,7 @@ module SknUtils
|
|
150
92
|
def remove(value)
|
151
93
|
target_node = find_by_value(value)
|
152
94
|
if target_node
|
153
|
-
if size == 1 # will become zero
|
95
|
+
if self.size == 1 # will become zero
|
154
96
|
@current = nil
|
155
97
|
self.head = nil
|
156
98
|
self.tail = nil
|
@@ -172,86 +114,11 @@ module SknUtils
|
|
172
114
|
end
|
173
115
|
end
|
174
116
|
|
175
|
-
|
176
|
-
def clear
|
177
|
-
rc = 0
|
178
|
-
node = head
|
179
|
-
position = head
|
180
|
-
while node do
|
181
|
-
node = node.remove!
|
182
|
-
rc += 1
|
183
|
-
break if position === node
|
184
|
-
end
|
185
|
-
|
186
|
-
@current = nil
|
187
|
-
self.head = nil
|
188
|
-
self.tail = nil
|
189
|
-
self.size = 0
|
190
|
-
rc
|
191
|
-
end
|
192
|
-
|
193
|
-
#
|
194
|
-
# Enumerate
|
195
|
-
#
|
196
|
-
|
197
|
-
# perform each() or return enumerator
|
198
|
-
def each(&block)
|
199
|
-
@current = head
|
200
|
-
position = head
|
201
|
-
if block_given?
|
202
|
-
while position do
|
203
|
-
block.call( position.value.dup )
|
204
|
-
position = position.next
|
205
|
-
break if position === @current
|
206
|
-
end
|
207
|
-
else
|
208
|
-
Enumerator.new do |yielder|
|
209
|
-
while position do
|
210
|
-
yielder << position.value.dup
|
211
|
-
position = position.next
|
212
|
-
break if position === @current
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
# convert self to a value array
|
219
|
-
def to_a
|
220
|
-
@current = head
|
221
|
-
position = head
|
222
|
-
result = []
|
223
|
-
while position do
|
224
|
-
result << position.value.dup
|
225
|
-
position = position.next
|
226
|
-
break if position === @current
|
227
|
-
end
|
228
|
-
result
|
229
|
-
end
|
230
|
-
|
231
|
-
# block format: sort condition : {|a_obj,b_obj| a_obj >= b_obj}
|
232
|
-
def sort!(direction_sym=:default, &compare_sort_proc)
|
233
|
-
@active_sort_condition = block_given? ? compare_sort_proc :
|
234
|
-
case direction_sym
|
235
|
-
when :asc
|
236
|
-
@sort_ascending
|
237
|
-
when :desc
|
238
|
-
@sort_descending
|
239
|
-
else
|
240
|
-
@sort_condition
|
241
|
-
end
|
242
|
-
sorted = merge_sort(to_a)
|
243
|
-
clear
|
244
|
-
sorted.each {|item| insert(item) }
|
245
|
-
size
|
246
|
-
end
|
247
|
-
|
248
|
-
private
|
249
|
-
|
250
|
-
attr_accessor :head, :tail
|
117
|
+
protected
|
251
118
|
|
252
119
|
def find_by_value(value)
|
253
|
-
return nil if head.nil? || value.nil? || size == 0
|
254
|
-
prior = head
|
120
|
+
return nil if self.head.nil? || value.nil? || self.size == 0
|
121
|
+
prior = self.head
|
255
122
|
target = prior
|
256
123
|
while target and not target.match_by_value(value)
|
257
124
|
prior = target
|
@@ -261,42 +128,13 @@ module SknUtils
|
|
261
128
|
end
|
262
129
|
|
263
130
|
def find_by_index(index)
|
264
|
-
return nil if head.nil? or index < 1 or index > size
|
265
|
-
node = head
|
131
|
+
return nil if self.head.nil? or index < 1 or index > self.size
|
132
|
+
node = self.head
|
266
133
|
node = node.next while ((index -= 1) > 0 and node.next)
|
267
134
|
@current = node if node
|
268
135
|
node
|
269
136
|
end
|
270
137
|
|
271
|
-
# Merged Sort via Ref: http://rubyalgorithms.com/merge_sort.html
|
272
|
-
# arr is Array to be sorted, sort_cond is Proc expecting a/b params returning true/false
|
273
|
-
def merge_sort(arr)
|
274
|
-
return arr if arr.size < 2
|
275
|
-
|
276
|
-
middle = arr.size / 2
|
277
|
-
|
278
|
-
left = merge_sort(arr[0...middle])
|
279
|
-
right = merge_sort(arr[middle..arr.size])
|
280
|
-
|
281
|
-
merge(left, right)
|
282
|
-
end
|
283
|
-
|
284
|
-
def merge(left, right)
|
285
|
-
sorted = []
|
286
|
-
|
287
|
-
while left.any? && right.any?
|
288
|
-
|
289
|
-
if @active_sort_condition.call(left.first, right.first)
|
290
|
-
sorted.push right.shift
|
291
|
-
else
|
292
|
-
sorted.push left.shift
|
293
|
-
end
|
294
|
-
|
295
|
-
end
|
296
|
-
|
297
|
-
sorted + left + right
|
298
|
-
end
|
299
|
-
|
300
138
|
end # end class
|
301
139
|
end # module
|
302
140
|
end # end module
|
@@ -8,10 +8,11 @@ module SknUtils
|
|
8
8
|
class LinkNode
|
9
9
|
attr_accessor :prev, :next, :value
|
10
10
|
|
11
|
-
def initialize(val, anchor_node=nil, strategy=:after, &cmp_key)
|
11
|
+
def initialize(val, anchor_node=nil, strategy=:after, mgr=nil, &cmp_key)
|
12
12
|
@value = val
|
13
13
|
@prev = nil
|
14
14
|
@next = nil
|
15
|
+
@provider = mgr
|
15
16
|
@cmp_proc = block_given? ? cmp_key : lambda {|a| a }
|
16
17
|
|
17
18
|
case strategy
|
@@ -55,6 +56,41 @@ module SknUtils
|
|
55
56
|
def to_s
|
56
57
|
"Node with value: #{@value}"
|
57
58
|
end
|
59
|
+
|
60
|
+
# Reverse API to Parent Linked List Class
|
61
|
+
def node_value
|
62
|
+
node_request.value
|
63
|
+
end
|
64
|
+
def first_node
|
65
|
+
node_request(:first)
|
66
|
+
end
|
67
|
+
def next_node
|
68
|
+
node_request(:next)
|
69
|
+
end
|
70
|
+
def current_node
|
71
|
+
node_request(:current)
|
72
|
+
end
|
73
|
+
def prev_node
|
74
|
+
node_request(:prev)
|
75
|
+
end
|
76
|
+
def last_node
|
77
|
+
node_request(:last)
|
78
|
+
end
|
79
|
+
|
80
|
+
protected()
|
81
|
+
|
82
|
+
def respond_to_missing?(method, include_private=false)
|
83
|
+
@provider && @provider.protected_methods(true).include?(method) || super
|
84
|
+
end
|
85
|
+
|
86
|
+
def method_missing(method, *args, &block)
|
87
|
+
if @provider and @provider.protected_methods(true).include?(method)
|
88
|
+
block_given? ? @provider.send(method, *args, block) :
|
89
|
+
(args.size == 0 ? @provider.send(method) : @provider.send(method, *args))
|
90
|
+
else
|
91
|
+
super
|
92
|
+
end
|
93
|
+
end
|
58
94
|
end
|
59
95
|
end # module
|
60
96
|
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
##
|
2
|
+
# File <SknUtils>/lib/skn_utils/lists/linked_commons.rb
|
3
|
+
#
|
4
|
+
# Common routines for Linked List:
|
5
|
+
# #initialize, #first, #next, #current, #last, #at_index,
|
6
|
+
# #insert, #prepend, #append, #empty?, #clear,
|
7
|
+
# #each, #to_a, and #sort!
|
8
|
+
##
|
9
|
+
|
10
|
+
module SknUtils
|
11
|
+
module Lists
|
12
|
+
|
13
|
+
class LinkedCommons
|
14
|
+
attr_accessor :size
|
15
|
+
|
16
|
+
# Initialize and return first node if nodes are available
|
17
|
+
def self.call(*vargs, &compare_key_proc)
|
18
|
+
target = self.new(*vargs, &compare_key_proc)
|
19
|
+
return target.instance_variable_get(:@current) if vargs.size > 1
|
20
|
+
target
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(*vargs, &compare_key_proc)
|
24
|
+
@current = nil
|
25
|
+
@head = nil
|
26
|
+
@tail = nil
|
27
|
+
@size = 0
|
28
|
+
|
29
|
+
@match_value = block_given? ? compare_key_proc : lambda {|obj| obj }
|
30
|
+
@sort_ascending = lambda {|a_obj,b_obj| @match_value.call(a_obj) >= @match_value.call(b_obj)}
|
31
|
+
@sort_descending = lambda {|a_obj,b_obj| @match_value.call(a_obj) <= @match_value.call(b_obj)}
|
32
|
+
@sort_condition = @sort_ascending
|
33
|
+
|
34
|
+
vargs.each {|value| insert(value) }
|
35
|
+
first if vargs.size > 1
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
# return values and position current to last node accessed
|
40
|
+
# prevent @current from nil assignment
|
41
|
+
def first
|
42
|
+
@current = self.head if self.head
|
43
|
+
@current.value rescue nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def next
|
47
|
+
@current = @current.next if @current and @current.next
|
48
|
+
@current.value rescue nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def current
|
52
|
+
@current.value rescue nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def last
|
56
|
+
@current = self.tail if self.tail
|
57
|
+
@current.value rescue nil
|
58
|
+
end
|
59
|
+
|
60
|
+
# return node at positive index from head
|
61
|
+
def at_index(index)
|
62
|
+
find_by_index(index)
|
63
|
+
current
|
64
|
+
end
|
65
|
+
|
66
|
+
def empty?
|
67
|
+
self.size == 0
|
68
|
+
end
|
69
|
+
|
70
|
+
# return number cleared
|
71
|
+
def clear
|
72
|
+
rc = 0
|
73
|
+
node = self.head
|
74
|
+
position = node
|
75
|
+
while node do
|
76
|
+
node = node.remove!
|
77
|
+
rc += 1
|
78
|
+
break if position.equal?(node)
|
79
|
+
end
|
80
|
+
|
81
|
+
@current = nil
|
82
|
+
self.head = nil
|
83
|
+
self.tail = nil
|
84
|
+
self.size = 0
|
85
|
+
rc
|
86
|
+
end
|
87
|
+
|
88
|
+
# return new size
|
89
|
+
def insert(value)
|
90
|
+
temp = @current.value rescue nil
|
91
|
+
insert_after(temp, value)
|
92
|
+
end
|
93
|
+
|
94
|
+
# return new size
|
95
|
+
def prepend(value)
|
96
|
+
temp = self.head.value rescue nil
|
97
|
+
insert_before(temp, value)
|
98
|
+
end
|
99
|
+
# return new size
|
100
|
+
def append(value)
|
101
|
+
temp = self.tail.value rescue nil
|
102
|
+
insert_after(temp, value)
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# Enumerate
|
107
|
+
#
|
108
|
+
|
109
|
+
# perform each() or return enumerator
|
110
|
+
def each(&block)
|
111
|
+
@current = self.head
|
112
|
+
position = self.head
|
113
|
+
if block_given?
|
114
|
+
while position do
|
115
|
+
block.call( position.value.dup )
|
116
|
+
position = position.next
|
117
|
+
break if position === @current
|
118
|
+
end
|
119
|
+
else
|
120
|
+
Enumerator.new do |yielder|
|
121
|
+
while position do
|
122
|
+
yielder << position.value.dup
|
123
|
+
position = position.next
|
124
|
+
break if position === @current
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# convert self to a value array
|
131
|
+
def to_a
|
132
|
+
@current = self.head
|
133
|
+
position = self.head
|
134
|
+
result = []
|
135
|
+
while position do
|
136
|
+
result << position.value.dup
|
137
|
+
position = position.next
|
138
|
+
break if position.equal?(@current)
|
139
|
+
end
|
140
|
+
result
|
141
|
+
end
|
142
|
+
|
143
|
+
# block format: sort condition : {|a_obj,b_obj| a_obj >= b_obj}
|
144
|
+
def sort!(direction_sym=:default, &compare_sort_proc)
|
145
|
+
@active_sort_condition = block_given? ? compare_sort_proc :
|
146
|
+
case direction_sym
|
147
|
+
when :asc
|
148
|
+
@sort_ascending
|
149
|
+
when :desc
|
150
|
+
@sort_descending
|
151
|
+
else
|
152
|
+
@sort_condition
|
153
|
+
end
|
154
|
+
sorted = merge_sort(self.to_a)
|
155
|
+
clear
|
156
|
+
sorted.each {|item| insert(item) }
|
157
|
+
self.size
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
protected
|
162
|
+
|
163
|
+
attr_accessor :head, :tail
|
164
|
+
|
165
|
+
# Merged Sort via Ref: http://rubyalgorithms.com/merge_sort.html
|
166
|
+
# arr is Array to be sorted, sort_cond is Proc expecting a/b params returning true/false
|
167
|
+
def merge_sort(arr)
|
168
|
+
return arr if arr.size < 2
|
169
|
+
middle = arr.size / 2
|
170
|
+
left = merge_sort(arr[0...middle])
|
171
|
+
right = merge_sort(arr[middle..arr.size])
|
172
|
+
merge(left, right)
|
173
|
+
end
|
174
|
+
|
175
|
+
def merge(left, right)
|
176
|
+
sorted = []
|
177
|
+
while left.any? && right.any?
|
178
|
+
if @active_sort_condition.call(left.first, right.first)
|
179
|
+
sorted.push right.shift
|
180
|
+
else
|
181
|
+
sorted.push left.shift
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
sorted + left + right
|
186
|
+
end
|
187
|
+
|
188
|
+
# Retrieves requested node, not value
|
189
|
+
def node_request(method_sym=:current, *vargs, &block)
|
190
|
+
position_value = block_given? ? send(method_sym, *vargs, block) :
|
191
|
+
(vargs.size == 0 ? send(method_sym) : send(method_sym, *vargs))
|
192
|
+
@current
|
193
|
+
end
|
194
|
+
# Retrieves requested value, not node
|
195
|
+
def node_value_request(method_sym=:current, *vargs, &block)
|
196
|
+
position_value = block_given? ? send(method_sym, *vargs, block) :
|
197
|
+
(vargs.size == 0 ? send(method_sym) : send(method_sym, *vargs))
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
end # module
|
202
|
+
end
|
@@ -28,51 +28,18 @@ module SknUtils
|
|
28
28
|
# Forward or #next navigation only
|
29
29
|
# Head is absolute via #first
|
30
30
|
# Tail when (next == nil)
|
31
|
-
class LinkedList
|
32
|
-
attr_accessor :size
|
33
31
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
@tail = nil
|
41
|
-
@size = 0
|
42
|
-
|
43
|
-
@match_value = block_given? ? compare_key_proc : lambda {|obj| obj }
|
44
|
-
@sort_ascending = lambda {|a_obj,b_obj| @match_value.call(a_obj) >= @match_value.call(b_obj)}
|
45
|
-
@sort_descending = lambda {|a_obj,b_obj| @match_value.call(a_obj) <= @match_value.call(b_obj)}
|
46
|
-
@sort_condition = @sort_ascending
|
47
|
-
|
48
|
-
vargs.each {|value| insert(value) }
|
49
|
-
first if vargs.size > 1
|
50
|
-
end
|
32
|
+
# LinkedCommons provides;
|
33
|
+
# - #initialize, #first, #next, #current, #last, #at_index,
|
34
|
+
# #insert, #prepend, #append, #empty?, #clear,
|
35
|
+
# #each, #to_a, and #sort!
|
36
|
+
#
|
37
|
+
class LinkedList < LinkedCommons
|
51
38
|
|
52
39
|
#
|
53
40
|
# Navigation
|
54
41
|
#
|
55
42
|
|
56
|
-
# return values and position current to last node accessed
|
57
|
-
def first
|
58
|
-
@current = head if head
|
59
|
-
@current.value rescue nil
|
60
|
-
end
|
61
|
-
|
62
|
-
def next
|
63
|
-
@current = @current.next if @current and @current.next
|
64
|
-
@current.value rescue nil
|
65
|
-
end
|
66
|
-
|
67
|
-
def current
|
68
|
-
@current.value rescue nil
|
69
|
-
end
|
70
|
-
|
71
|
-
def last
|
72
|
-
@current = tail if tail
|
73
|
-
@current.value rescue nil
|
74
|
-
end
|
75
|
-
|
76
43
|
# +int position from current node
|
77
44
|
def nth(index)
|
78
45
|
node = @current
|
@@ -85,45 +52,17 @@ module SknUtils
|
|
85
52
|
current
|
86
53
|
end
|
87
54
|
|
88
|
-
# return node at positive index from head
|
89
|
-
def at_index(index)
|
90
|
-
find_by_index(index)
|
91
|
-
current
|
92
|
-
end
|
93
|
-
|
94
|
-
def empty?
|
95
|
-
size == 0
|
96
|
-
end
|
97
|
-
|
98
55
|
#
|
99
56
|
# Modifications
|
100
57
|
#
|
101
58
|
|
102
|
-
# return new size
|
103
|
-
def insert(value)
|
104
|
-
temp = @current.value rescue nil
|
105
|
-
insert_after(temp, value)
|
106
|
-
end
|
107
|
-
|
108
|
-
# return new size
|
109
|
-
def prepend(value)
|
110
|
-
temp = head.value rescue nil
|
111
|
-
insert_before(temp, value)
|
112
|
-
end
|
113
|
-
|
114
|
-
# return new size
|
115
|
-
def append(value)
|
116
|
-
temp = tail.value rescue nil
|
117
|
-
insert_after(temp, value)
|
118
|
-
end
|
119
|
-
|
120
59
|
# return new size
|
121
60
|
def insert_before(position_value, value)
|
122
61
|
prior, target = find_by_value(position_value)
|
123
|
-
node = LinkNode.new(value, prior, :single, &@match_value)
|
62
|
+
node = LinkNode.new(value, prior, :single, self, &@match_value)
|
124
63
|
node.next = target if target
|
125
|
-
self.head = node if head === target
|
126
|
-
self.tail = node if tail.nil?
|
64
|
+
self.head = node if self.head === target
|
65
|
+
self.tail = node if self.tail.nil?
|
127
66
|
@current = node
|
128
67
|
self.size += 1
|
129
68
|
end
|
@@ -131,9 +70,9 @@ module SknUtils
|
|
131
70
|
# return new size
|
132
71
|
def insert_after(position_value, value)
|
133
72
|
prior, target = find_by_value(position_value)
|
134
|
-
node = LinkNode.new(value, target, :single, &@match_value)
|
135
|
-
self.head = node if head.nil?
|
136
|
-
self.tail = node if tail === target
|
73
|
+
node = LinkNode.new(value, target, :single, self, &@match_value)
|
74
|
+
self.head = node if self.head.nil?
|
75
|
+
self.tail = node if self.tail === target
|
137
76
|
@current = node
|
138
77
|
self.size += 1
|
139
78
|
end
|
@@ -143,90 +82,16 @@ module SknUtils
|
|
143
82
|
prior, target_node = find_by_value(value)
|
144
83
|
@current = prior.nil? ? target_node.next : prior
|
145
84
|
@current.next = target_node.remove! if @current && target_node
|
146
|
-
self.tail = @current.next if @current && tail === target_node
|
147
|
-
self.head = @current.next if @current && head === target_node
|
85
|
+
self.tail = @current.next if @current && self.tail === target_node
|
86
|
+
self.head = @current.next if @current && self.head === target_node
|
148
87
|
self.size -= 1
|
149
88
|
end
|
150
89
|
|
151
|
-
|
152
|
-
def clear
|
153
|
-
rc = 0
|
154
|
-
node = head
|
155
|
-
position = head
|
156
|
-
while node do
|
157
|
-
node = node.remove!
|
158
|
-
rc += 1
|
159
|
-
break if position === node
|
160
|
-
end
|
161
|
-
|
162
|
-
@current = nil
|
163
|
-
self.head = nil
|
164
|
-
self.tail = nil
|
165
|
-
self.size = 0
|
166
|
-
rc
|
167
|
-
end
|
168
|
-
|
169
|
-
#
|
170
|
-
# Enumerate
|
171
|
-
#
|
172
|
-
|
173
|
-
# perform each() or return enumerator
|
174
|
-
def each(&block)
|
175
|
-
@current = head
|
176
|
-
position = head
|
177
|
-
if block_given?
|
178
|
-
while position do
|
179
|
-
block.call(position.value.dup )
|
180
|
-
position = position.next
|
181
|
-
end
|
182
|
-
else
|
183
|
-
Enumerator.new do |yielder|
|
184
|
-
while position do
|
185
|
-
yielder << position.value.dup
|
186
|
-
position = position.next
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
# convert self to a value array
|
193
|
-
def to_a
|
194
|
-
@current = head
|
195
|
-
position = head
|
196
|
-
result = []
|
197
|
-
while position do
|
198
|
-
result << position.value.dup
|
199
|
-
position = position.next
|
200
|
-
break if position === @current
|
201
|
-
end
|
202
|
-
result
|
203
|
-
end
|
204
|
-
|
205
|
-
# block format: sort condition : {|a_obj,b_obj| a_obj >= b_obj}
|
206
|
-
def sort!(direction_sym=:default, &compare_sort_proc)
|
207
|
-
@active_sort_condition = block_given? ? compare_sort_proc :
|
208
|
-
case direction_sym
|
209
|
-
when :asc
|
210
|
-
@sort_ascending
|
211
|
-
when :desc
|
212
|
-
@sort_descending
|
213
|
-
else
|
214
|
-
@sort_condition
|
215
|
-
end
|
216
|
-
|
217
|
-
sorted = merge_sort(to_a)
|
218
|
-
clear
|
219
|
-
sorted.each {|item| insert(item) }
|
220
|
-
size
|
221
|
-
end
|
222
|
-
|
223
|
-
private
|
224
|
-
|
225
|
-
attr_accessor :head, :tail
|
90
|
+
protected
|
226
91
|
|
227
92
|
def find_by_value(value)
|
228
|
-
return [@current, nil] if head.nil? || value.nil?
|
229
|
-
prior = head
|
93
|
+
return [@current, nil] if self.head.nil? || value.nil?
|
94
|
+
prior = self.head
|
230
95
|
target = prior
|
231
96
|
while target and not target.match_by_value(value)
|
232
97
|
prior = target
|
@@ -237,42 +102,13 @@ module SknUtils
|
|
237
102
|
end
|
238
103
|
|
239
104
|
def find_by_index(index)
|
240
|
-
return nil if head.nil? || index < 1 || index > size
|
241
|
-
node = head
|
105
|
+
return nil if self.head.nil? || index < 1 || index > self.size
|
106
|
+
node = self.head
|
242
107
|
node = node.next while ((index -= 1) > 0 and node.next)
|
243
108
|
@current = node if node
|
244
109
|
node
|
245
110
|
end
|
246
111
|
|
247
|
-
# Merged Sort via Ref: http://rubyalgorithms.com/merge_sort.html
|
248
|
-
# arr is Array to be sorted, sort_cond is Proc expecting a/b params returning true/false
|
249
|
-
def merge_sort(arr)
|
250
|
-
return arr if arr.size < 2
|
251
|
-
|
252
|
-
middle = arr.size / 2
|
253
|
-
|
254
|
-
left = merge_sort(arr[0...middle])
|
255
|
-
right = merge_sort(arr[middle..arr.size])
|
256
|
-
|
257
|
-
merge(left, right)
|
258
|
-
end
|
259
|
-
|
260
|
-
def merge(left, right)
|
261
|
-
sorted = []
|
262
|
-
|
263
|
-
while left.any? && right.any?
|
264
|
-
|
265
|
-
if @active_sort_condition.call(left.first, right.first)
|
266
|
-
sorted.push right.shift
|
267
|
-
else
|
268
|
-
sorted.push left.shift
|
269
|
-
end
|
270
|
-
|
271
|
-
end
|
272
|
-
|
273
|
-
sorted + left + right
|
274
|
-
end
|
275
|
-
|
276
112
|
end # end class
|
277
113
|
end # end module
|
278
114
|
end # end module
|
data/lib/skn_utils/version.rb
CHANGED
data/lib/skn_utils.rb
CHANGED
@@ -5,6 +5,7 @@ require 'skn_utils/page_controls'
|
|
5
5
|
require 'skn_utils/null_object'
|
6
6
|
require 'skn_utils/notifier_base'
|
7
7
|
require 'skn_utils/skn_configuration'
|
8
|
+
require 'skn_utils/lists/linked_commons'
|
8
9
|
require 'skn_utils/lists/link_node'
|
9
10
|
require 'skn_utils/lists/linked_list'
|
10
11
|
require 'skn_utils/lists/doubly_linked_list'
|
@@ -0,0 +1,85 @@
|
|
1
|
+
##
|
2
|
+
# spec/lib/skn_utils/node_based_linked_list_spec.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
RSpec.describe SknUtils::Lists::DoublyLinkedList, "DoublyLinkedList using node interface " do
|
6
|
+
|
7
|
+
context "Node Interface Edge Cases " do
|
8
|
+
let(:node) { described_class.call(10,20, 30, 40, 50, 60, 70, 80, 90, 100) {|a| a} }
|
9
|
+
|
10
|
+
context "Node Retrieval " do
|
11
|
+
|
12
|
+
it "#node_request(:first) returns a LinkedNode object." do
|
13
|
+
expect(node.send(:node_request,:first)).to be_a SknUtils::Lists::LinkNode
|
14
|
+
end
|
15
|
+
it "#first_node returns a LinkedNode object." do
|
16
|
+
expect(node.first_node).to be_a SknUtils::Lists::LinkNode
|
17
|
+
end
|
18
|
+
it "#next_node returns a LinkedNode object." do
|
19
|
+
expect(node.next_node).to be_a SknUtils::Lists::LinkNode
|
20
|
+
end
|
21
|
+
it "#current_node returns a LinkedNode object." do
|
22
|
+
expect(node.current_node).to be_a SknUtils::Lists::LinkNode
|
23
|
+
end
|
24
|
+
it "#prev_node returns a LinkedNode object." do
|
25
|
+
expect(node.prev_node).to be_a SknUtils::Lists::LinkNode
|
26
|
+
end
|
27
|
+
it "#last_node returns a LinkedNode object." do
|
28
|
+
expect(node.last_node).to be_a SknUtils::Lists::LinkNode
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "Node Values " do
|
33
|
+
|
34
|
+
it "#methods with params are supported through #{}node_request() interface. " do
|
35
|
+
expect(node.first_node.node_value_request(:at_index, 5)).to eq(50)
|
36
|
+
end
|
37
|
+
it "First node has the expected value. " do
|
38
|
+
expect(node.first_node.value).to eq(10)
|
39
|
+
end
|
40
|
+
it "Next node has the expected value. " do
|
41
|
+
expect(node.next_node.value).to eq(20)
|
42
|
+
end
|
43
|
+
it "Current node has the expected value. " do
|
44
|
+
3.times { node.next_node }
|
45
|
+
expect(node.current_node.value).to eq(40)
|
46
|
+
end
|
47
|
+
it "Last node has the expected value. " do
|
48
|
+
expect(node.last_node.value).to eq(100)
|
49
|
+
end
|
50
|
+
it "#node_value collected match #to_a output. " do
|
51
|
+
nav_ary = []
|
52
|
+
node.node_value_request(:size).times do
|
53
|
+
nav_ary << node.node_value
|
54
|
+
node.next_node
|
55
|
+
end
|
56
|
+
|
57
|
+
expect(nav_ary).to eq(node.node_value_request(:to_a))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "Node Navigation " do
|
62
|
+
|
63
|
+
it "Can navigate to each mode in list, forward. " do
|
64
|
+
node.node_value_request(:size).times do
|
65
|
+
expect(node.next_node).to be_a SknUtils::Lists::LinkNode
|
66
|
+
end
|
67
|
+
end
|
68
|
+
it "Can navigate to each mode in list, backward. " do
|
69
|
+
node.last_node.node_value_request(:size).times do
|
70
|
+
expect(node.prev_node).to be_a SknUtils::Lists::LinkNode
|
71
|
+
end
|
72
|
+
end
|
73
|
+
it "Values collected match #to_a output. " do
|
74
|
+
nav_ary = []
|
75
|
+
node.node_value_request(:size).times do
|
76
|
+
nav_ary << node.node_value
|
77
|
+
node.next_node
|
78
|
+
end
|
79
|
+
|
80
|
+
expect(node.node_value_request(:to_a)).to eq(nav_ary)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skn_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.3.
|
4
|
+
version: 3.3.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Scott Jr
|
@@ -140,6 +140,7 @@ files:
|
|
140
140
|
- lib/skn_utils/lists/circular_linked_list.rb
|
141
141
|
- lib/skn_utils/lists/doubly_linked_list.rb
|
142
142
|
- lib/skn_utils/lists/link_node.rb
|
143
|
+
- lib/skn_utils/lists/linked_commons.rb
|
143
144
|
- lib/skn_utils/lists/linked_list.rb
|
144
145
|
- lib/skn_utils/nested_result.rb
|
145
146
|
- lib/skn_utils/notifier_base.rb
|
@@ -159,6 +160,7 @@ files:
|
|
159
160
|
- spec/lib/skn_utils/lists/Circular_linked_list_spec.rb
|
160
161
|
- spec/lib/skn_utils/lists/doubly_linked_list_spec.rb
|
161
162
|
- spec/lib/skn_utils/lists/linked_list_spec.rb
|
163
|
+
- spec/lib/skn_utils/lists/node_based_linked_list_spec.rb
|
162
164
|
- spec/lib/skn_utils/nested_result_spec.rb
|
163
165
|
- spec/lib/skn_utils/notifier_base_spec.rb
|
164
166
|
- spec/lib/skn_utils/null_object_spec.rb
|
@@ -204,6 +206,7 @@ test_files:
|
|
204
206
|
- spec/lib/skn_utils/lists/Circular_linked_list_spec.rb
|
205
207
|
- spec/lib/skn_utils/lists/doubly_linked_list_spec.rb
|
206
208
|
- spec/lib/skn_utils/lists/linked_list_spec.rb
|
209
|
+
- spec/lib/skn_utils/lists/node_based_linked_list_spec.rb
|
207
210
|
- spec/lib/skn_utils/nested_result_spec.rb
|
208
211
|
- spec/lib/skn_utils/notifier_base_spec.rb
|
209
212
|
- spec/lib/skn_utils/null_object_spec.rb
|