linked-list 0.0.10 → 0.0.11

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
  SHA256:
3
- metadata.gz: 15032f04d676c41f8dedbb0d911c82a35944826d5469c3a32530548fc55efa5c
4
- data.tar.gz: 3f8b4bab1f5d9dca9f88b2e4e9baa78b2e9120eaf41ad7c3095e4072b7609be9
3
+ metadata.gz: 203cf979a2f074eaa22dd987096ecf8ec298198344ddf1f8cafafca20be8552b
4
+ data.tar.gz: e8fc8a7584f411444d4685aa3c9ecc7328a2ba59f1f0e0de55a1abb2130ff63f
5
5
  SHA512:
6
- metadata.gz: c174a97b29c738a4224025639b744c97f086f0cc80afe21f20678ea708be29ff956fd8e81feb4f606d7a1ac9376f2fb334afe7bd730e3b8263af69107255bc50
7
- data.tar.gz: 0eeb55908b8b9ddeb7f477262899e1a8d990e013af21d0c723c64a9c92248b4a1964e48450f379de1642906c0f68e08ea4a7f20dda360e45346a4ce9dd057a4d
6
+ metadata.gz: 4e87238b13c8a4621ff4b30502f6d4295df7f9ad7a219144bfcdbea24c7676b859767f53b3070ac11707576f639a8f1323bd1e96903bcba76403c1a865a2d552
7
+ data.tar.gz: 9419f5694a938f436084247464b016c213b8914fdbcc3a255eed8fffbe21164938f6b10f27aac2187d985995c1120b6bbc581ea6c295a8fd7da45f5acbe01655
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
- - 2.0.0
3
+ - 2.3.0
4
+ - 2.5.0
5
5
  cache: bundler
@@ -0,0 +1,17 @@
1
+ # 0.0.11 / 2018-04-02
2
+
3
+ ## Added
4
+
5
+ - Added `delete` and `delete_all` methods (mpospelov in [#2](https://github.com/spectator/linked-list/pull/2))
6
+
7
+ # 0.0.10 / 2018-04-02
8
+
9
+ ## Fixed
10
+
11
+ - Fixed bug when `@tail.prev` was mistekenly set to `nil` instead of `@tail.next` when popping elements off the list (Sonna in [#1](https://github.com/spectator/linked-list/pull/1))
12
+
13
+ [Compare v0.0.9...v0.0.10](https://github.com/spectator/linked-list/compare/v0.0.9...v0.0.10)
14
+
15
+ # 0.0.9 / 2013-12-11
16
+
17
+ Initial release.
data/README.md CHANGED
@@ -44,6 +44,9 @@ list.shift
44
44
  list.reverse
45
45
  list.reverse!
46
46
 
47
+ list.delete(object)
48
+ list.delete_all(object)
49
+
47
50
  list.each # Enumerator object
48
51
  list.each { |e| puts e }
49
52
 
@@ -78,7 +81,7 @@ Please see `LinkedList::List`, `LinkedList::Node`, and
78
81
 
79
82
  ## TODO
80
83
 
81
- * Insert / delete in the middle
84
+ * Insert in the middle
82
85
 
83
86
  ## Tests
84
87
 
@@ -12,8 +12,7 @@ module LinkedList
12
12
  # New +Node+ object.
13
13
  #
14
14
  def Node(arg)
15
- case arg
16
- when ->(_arg) { _arg.respond_to?(:to_node) }
15
+ if arg.respond_to?(:to_node)
17
16
  arg.to_node
18
17
  else
19
18
  Node.new(arg)
@@ -31,10 +30,9 @@ module LinkedList
31
30
  # New +List+ object.
32
31
  #
33
32
  def List(arg)
34
- case arg
35
- when ->(_arg) { _arg.respond_to?(:to_list) }
33
+ if arg.respond_to?(:to_list)
36
34
  arg.to_list
37
- when ->(_arg) { _arg.respond_to?(:to_ary) }
35
+ elsif arg.respond_to?(:to_ary)
38
36
  arg.to_ary.each_with_object(List.new) { |n, l| l.push(Node(n)) }
39
37
  else
40
38
  List.new.push(Node(arg))
@@ -4,7 +4,7 @@ module LinkedList
4
4
  class List
5
5
  include Conversions
6
6
 
7
- attr_reader :length
7
+ attr_reader :length
8
8
  alias_method :size, :length
9
9
 
10
10
  def initialize
@@ -69,6 +69,30 @@ module LinkedList
69
69
  self
70
70
  end
71
71
 
72
+ # Removes first matched node.data from the the list by passed block or value.
73
+ #
74
+ # == Returns:
75
+ # Deleted node
76
+ #
77
+ def delete(val = nil, &block)
78
+ each_node.find(&__to_matcher(val, &block)).tap do |node_to_delete|
79
+ return if node_to_delete.blank?
80
+ __unlink(node_to_delete)
81
+ end.data
82
+ end
83
+
84
+ # Removes all matched data.data from the the list by passed block or value.
85
+ #
86
+ # == Returns:
87
+ # Array of deleted nodes
88
+ #
89
+ def delete_all(val = nil, &block)
90
+ each_node.select(&__to_matcher(val, &block)).each do |node_to_delete|
91
+ next if node_to_delete.blank?
92
+ __unlink(node_to_delete)
93
+ end.map(&:data)
94
+ end
95
+
72
96
  # Removes data from the end of the list.
73
97
  #
74
98
  # == Returns:
@@ -136,6 +160,17 @@ module LinkedList
136
160
  __each { |node| yield(node.data) }
137
161
  end
138
162
 
163
+ # Iterates over nodes from top to bottom passing node(LinkedList::Node instance)
164
+ # to the block if given. If no block given, returns +Enumerator+.
165
+ #
166
+ # == Returns:
167
+ # +Enumerator+ or yields list nodes to the block
168
+ #
169
+ def each_node
170
+ return to_enum(__callee__) unless block_given?
171
+ __each { |node| yield(node) }
172
+ end
173
+
139
174
  # Converts list to array.
140
175
  #
141
176
  def to_a
@@ -158,6 +193,25 @@ module LinkedList
158
193
 
159
194
  private
160
195
 
196
+ def __to_matcher(val = nil, &block)
197
+ raise ArgumentError, 'either value or block should be passed' if val && block_given?
198
+ block = ->(e) { e == val } unless block_given?
199
+ -> (node) { block.call(node.data) }
200
+ end
201
+
202
+ def __unlink(node)
203
+ if node.prev.blank?
204
+ node.next.prev = nil if node.next
205
+ @head = node.next
206
+ elsif node.next.blank?
207
+ node.prev.next = nil if node.prev
208
+ @tail = node.prev
209
+ else
210
+ node.prev.next, node.next.prev = node.next, node.prev
211
+ end
212
+ @length -= 1
213
+ end
214
+
161
215
  def __shift
162
216
  head = @head
163
217
  @head = @head.next
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Linked
4
4
  module List
5
- VERSION = '0.0.10'
5
+ VERSION = '0.0.11'
6
6
  end
7
7
  end
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Linked::List::VERSION
9
9
  spec.authors = ['Yury Velikanau']
10
10
  spec.email = ['yury.velikanau@gmail.com']
11
- spec.description = %q{Ruby implementation of Doubly Linked List, following some Ruby idioms.}
12
- spec.summary = %q{Ruby implementation of Doubly Linked List, following some Ruby idioms.}
11
+ spec.description = %q(Ruby implementation of Doubly Linked List, following some Ruby idioms.)
12
+ spec.summary = %q(Ruby implementation of Doubly Linked List, following some Ruby idioms.)
13
13
  spec.homepage = 'https://github.com/spectator/linked-list'
14
14
  spec.license = 'MIT'
15
15
 
@@ -18,8 +18,9 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_development_dependency 'rake'
22
- spec.add_development_dependency 'bundler', '>= 1.3', '<= 2.0'
23
- spec.add_development_dependency 'minitest', '>= 5.0', '<= 6.0'
21
+ spec.add_development_dependency 'bundler', '>= 1.3', '<= 2.0'
24
22
  spec.add_development_dependency 'coveralls'
23
+ spec.add_development_dependency 'm', '~> 1.5.0'
24
+ spec.add_development_dependency 'minitest', '>= 5.0', '<= 6.0'
25
+ spec.add_development_dependency 'rake'
25
26
  end
@@ -134,6 +134,193 @@ describe LinkedList::List do
134
134
  end
135
135
  end
136
136
 
137
+
138
+ describe '#delete' do
139
+ it 'raises error if block and value are passed' do
140
+ err = assert_raises ArgumentError do
141
+ assert_nil list.delete('x') { |d| d == 'x' }
142
+ end
143
+ assert_equal err.message, 'either value or block should be passed'
144
+ end
145
+
146
+ describe 'by block' do
147
+ it 'returns nil if list is empty' do
148
+ assert_nil list.delete { |d| d == 'x' }
149
+ end
150
+
151
+ it 'deletes value in first matching node' do
152
+ list.push('foo')
153
+ list.push('foo')
154
+ list.push('bar')
155
+ list.push('foo')
156
+ list.delete { |d| d == 'foo' }
157
+ assert_equal ['foo', 'bar', 'foo'], list.to_a
158
+ end
159
+
160
+ it 'returns deleted value' do
161
+ list.push('foo')
162
+ assert_equal 'foo', list.delete { |d| d == 'foo' }
163
+ end
164
+
165
+ it 'decreases length of list' do
166
+ list.push('foo')
167
+ list.push('bar')
168
+ list.push('foo')
169
+ list.delete { |d| d == 'foo' }
170
+ assert_equal 2, list.length
171
+ assert_equal ['bar', 'foo'], list.to_a
172
+ end
173
+
174
+ describe 'position edge cases' do
175
+ before do
176
+ list.push(0)
177
+ list.push(1)
178
+ list.push(2)
179
+ end
180
+
181
+ it 'deletes value from head' do
182
+ list.delete { |d| d == 0 }
183
+ assert_equal [1, 2], list.to_a
184
+ assert_equal 1, list.first
185
+ end
186
+
187
+ it 'deletes value from middle' do
188
+ list.delete { |d| d == 1 }
189
+ assert_equal [0, 2], list.to_a
190
+ end
191
+
192
+
193
+ it 'deletes value from tail' do
194
+ list.delete { |d| d == 2 }
195
+ assert_equal [0, 1], list.to_a
196
+ assert_equal 1, list.last
197
+ end
198
+ end
199
+ end
200
+
201
+ describe 'by data equality' do
202
+ it 'returns nil if list is empty' do
203
+ assert_nil list.delete('x')
204
+ end
205
+
206
+ it 'deletes value in first node' do
207
+ list.push('foo')
208
+ list.push('foo')
209
+ list.push('bar')
210
+ list.push('foo')
211
+ list.delete('foo')
212
+ assert_equal ['foo', 'bar', 'foo'], list.to_a
213
+ end
214
+
215
+ it 'returns deleted value' do
216
+ list.push('foo')
217
+ assert_equal 'foo', list.delete('foo')
218
+ end
219
+
220
+ it 'decreases length of list' do
221
+ list.push('foo')
222
+ list.push('bar')
223
+ list.push('foo')
224
+ list.delete('foo')
225
+ assert_equal 2, list.length
226
+ assert_equal ['bar', 'foo'], list.to_a
227
+ end
228
+
229
+ describe 'position edge cases' do
230
+ before do
231
+ list.push(0)
232
+ list.push(1)
233
+ list.push(2)
234
+ end
235
+
236
+ it 'deletes value from head' do
237
+ list.delete(0)
238
+ assert_equal [1, 2], list.to_a
239
+ assert_equal 1, list.first
240
+ end
241
+
242
+ it 'deletes value from middle' do
243
+ list.delete(1)
244
+ assert_equal [0, 2], list.to_a
245
+ end
246
+
247
+
248
+ it 'deletes value from tail' do
249
+ list.delete(2)
250
+ assert_equal [0, 1], list.to_a
251
+ assert_equal 1, list.last
252
+ end
253
+ end
254
+ end
255
+ end
256
+
257
+ describe '#delete_all' do
258
+ it 'raises error if block and value are passed' do
259
+ err = assert_raises ArgumentError do
260
+ assert_nil list.delete_all('x') { |d| d == 'x' }
261
+ end
262
+ assert_equal err.message, 'either value or block should be passed'
263
+ end
264
+
265
+ describe 'by block' do
266
+ it 'returns nil if list is empty' do
267
+ assert_equal list.delete_all { |d| d == 'x' }, []
268
+ end
269
+
270
+ it 'deletes value in first matching node' do
271
+ list.push('foo')
272
+ list.push('foo')
273
+ list.push('bar')
274
+ list.push('foo')
275
+ list.delete_all { |d| d == 'foo' }
276
+ assert_equal ['bar'], list.to_a
277
+ end
278
+
279
+ it 'returns deleted value' do
280
+ list.push('foo')
281
+ assert_equal ['foo'], list.delete_all { |d| d == 'foo' }
282
+ end
283
+
284
+ it 'decreases length of list' do
285
+ list.push('foo')
286
+ list.push('bar')
287
+ list.push('foo')
288
+ list.delete_all { |d| d == 'foo' }
289
+ assert_equal 1, list.length
290
+ assert_equal ['bar'], list.to_a
291
+ end
292
+ end
293
+
294
+ describe 'by data equality' do
295
+ it 'returns nil if list is empty' do
296
+ assert_nil list.delete('x')
297
+ end
298
+
299
+ it 'deletes all matched values' do
300
+ list.push('foo')
301
+ list.push('foo')
302
+ list.push('bar')
303
+ list.push('foo')
304
+ list.delete_all('foo')
305
+ assert_equal ['bar'], list.to_a
306
+ end
307
+
308
+ it 'returns deleted value' do
309
+ list.push('foo')
310
+ assert_equal ['foo'], list.delete_all('foo')
311
+ end
312
+
313
+ it 'decreases length of list' do
314
+ list.push('foo')
315
+ list.push('bar')
316
+ list.push('foo')
317
+ list.delete_all('foo')
318
+ assert_equal 1, list.length
319
+ assert_equal ['bar'], list.to_a
320
+ end
321
+ end
322
+ end
323
+
137
324
  describe '#shift' do
138
325
  it 'returns nil if list is empty' do
139
326
  assert_nil list.shift
@@ -200,6 +387,21 @@ describe LinkedList::List do
200
387
  end
201
388
  end
202
389
 
390
+ describe '#each_node' do
391
+ it 'returns enumerator if no block given' do
392
+ assert_instance_of Enumerator, list.each_node
393
+ end
394
+
395
+ it 'pass each node data to the block' do
396
+ list.push(node_1)
397
+ list.push(node_2)
398
+ nodes = []
399
+ list.each_node { |e| nodes << e }
400
+ assert_equal %w(foo bar), nodes.map(&:data)
401
+ assert_equal true, nodes.all? { |n| n.is_a?(LinkedList::Node) }
402
+ end
403
+ end
404
+
203
405
  describe '#each' do
204
406
  it 'returns enumerator if no block given' do
205
407
  assert_instance_of Enumerator, list.each
metadata CHANGED
@@ -1,49 +1,63 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: linked-list
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yury Velikanau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-03 00:00:00.000000000 Z
11
+ date: 2018-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rake
14
+ name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '1.3'
20
+ - - "<="
21
+ - !ruby/object:Gem::Version
22
+ version: '2.0'
20
23
  type: :development
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - ">="
25
28
  - !ruby/object:Gem::Version
26
- version: '0'
29
+ version: '1.3'
30
+ - - "<="
31
+ - !ruby/object:Gem::Version
32
+ version: '2.0'
27
33
  - !ruby/object:Gem::Dependency
28
- name: bundler
34
+ name: coveralls
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - ">="
32
38
  - !ruby/object:Gem::Version
33
- version: '1.3'
34
- - - "<="
35
- - !ruby/object:Gem::Version
36
- version: '2.0'
39
+ version: '0'
37
40
  type: :development
38
41
  prerelease: false
39
42
  version_requirements: !ruby/object:Gem::Requirement
40
43
  requirements:
41
44
  - - ">="
42
45
  - !ruby/object:Gem::Version
43
- version: '1.3'
44
- - - "<="
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: m
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
45
52
  - !ruby/object:Gem::Version
46
- version: '2.0'
53
+ version: 1.5.0
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 1.5.0
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: minitest
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -65,7 +79,7 @@ dependencies:
65
79
  - !ruby/object:Gem::Version
66
80
  version: '6.0'
67
81
  - !ruby/object:Gem::Dependency
68
- name: coveralls
82
+ name: rake
69
83
  requirement: !ruby/object:Gem::Requirement
70
84
  requirements:
71
85
  - - ">="
@@ -89,6 +103,7 @@ extra_rdoc_files: []
89
103
  files:
90
104
  - ".gitignore"
91
105
  - ".travis.yml"
106
+ - CHANGELOG.md
92
107
  - Gemfile
93
108
  - LICENSE.txt
94
109
  - README.md