linked-list 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
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