linked 0.1.1 → 0.1.2

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: 513dbae22fea14a370f2181ef4da797264121631
4
- data.tar.gz: 685eb16cb3380aec648af578118b54416af20772
3
+ metadata.gz: ea4e0ba7b896f4e64d885d73066e65e4e08b49ea
4
+ data.tar.gz: 7913edd077d33d5a7b36982568d5b3cb46cc7c1e
5
5
  SHA512:
6
- metadata.gz: b3cfa2318674d45841c7a075250cb88d1095a5df6c56a270eda3bf60bce06cd41db8612f1d1df520cd9ab32ded2f73aedb36f71e1fb410c7d875e77f4d128e62
7
- data.tar.gz: 6557225296323c2ff767766bde4ea13067e39103bc84a9e3fb43229991ca65156373475ad7091412174608c11c4b7bdf889274d96d975e9fee3bd493a1f8aab0
6
+ metadata.gz: 1467066f7e5af4ddc7eca82013d94777b956d7c93497502977fd776523e570bb7ae0d441940cb9a275f567c48750a50cff80881de98e1ca89c1592b7a5aff599
7
+ data.tar.gz: fac1a3393906af1c00f788fbc4e5eb30ab2b48e042190f898b43944a6ae4718baec62b9c0e0193537cc4f484f4a518f435abf0a7611bb5f28215d6aa8128b54f
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Linked
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/linked.svg)](https://badge.fury.io/rb/linked)
3
4
  [![Build Status](https://travis-ci.org/seblindberg/ruby-linked.svg?branch=master)](https://travis-ci.org/seblindberg/ruby-linked)
4
5
  [![Coverage Status](https://coveralls.io/repos/github/seblindberg/ruby-linked/badge.svg?branch=master)](https://coveralls.io/github/seblindberg/ruby-linked?branch=master)
5
6
  [![Inline docs](http://inch-ci.org/github/seblindberg/ruby-linked.svg?branch=master)](http://inch-ci.org/github/seblindberg/ruby-linked)
data/lib/linked/item.rb CHANGED
@@ -56,12 +56,12 @@ module Linked
56
56
  @prev = nil
57
57
  end
58
58
  end
59
-
59
+
60
60
  # Calling #dup on an item returns a copy that is no longer connected to the
61
61
  # original item chain, or the list. The value will also be copied.
62
62
  #
63
63
  # Returns a new Item.
64
-
64
+
65
65
  def initialize_dup(source)
66
66
  @next = @prev = @list = nil
67
67
  @value = begin
@@ -326,21 +326,21 @@ module Linked
326
326
  item = item.next
327
327
  end
328
328
  end
329
-
329
+
330
330
  # Freezes the value, as well as making the list item itself immutable.
331
-
331
+
332
332
  def freeze
333
333
  value.freeze
334
334
  super
335
335
  end
336
-
336
+
337
337
  # The default #inspect method becomes very cluttered the moment you start
338
338
  # liking objects together. This implementation fixes that and only shows the
339
339
  # class name, object id and value (if set).
340
-
340
+
341
341
  def inspect
342
342
  return yield self if block_given?
343
-
343
+
344
344
  output = format '%s:0x%0x', self.class.name, object_id
345
345
  value ? output + " value=#{value.inspect}" : output
346
346
  end
data/lib/linked/list.rb CHANGED
@@ -46,67 +46,81 @@ module Linked
46
46
  def initialize(*)
47
47
  @eol = EOL.new list: self
48
48
  @item_count = 0
49
-
49
+
50
50
  super
51
51
  end
52
-
52
+
53
53
  # When copying a list its entire item chain needs to be copied as well.
54
54
  # Therefore #dup will be called on each of the original lists items, making
55
55
  # this operation quite expensive.
56
-
56
+
57
57
  def initialize_dup(source)
58
58
  @eol = EOL.new list: self
59
59
  @item_count = 0
60
-
60
+
61
61
  source.each_item { |item| push item.dup }
62
-
62
+
63
63
  super
64
64
  end
65
65
 
66
- # Access the first n item(s) in the list.
66
+ # Access the first n item(s) in the list. If a block is given each item will
67
+ # be yielded to it. The first item, starting from the first in the list, for
68
+ # which the block returns true and the n - 1 items directly following it
69
+ # will be returned.
67
70
  #
68
71
  # n - the number of items to return.
69
72
  #
70
- # Returns the first item, or an array of items if n > 1.
73
+ # Returns, for different values of n:
74
+ # n == 0) nil
75
+ # n == 1) an item if the list contains one, or nil
76
+ # n > 1) an array of between 0 and n items, depending on how many are in
77
+ # the list
71
78
 
72
- def first(*args)
73
- if args.empty?
74
- eol.next!
75
- else
76
- super
79
+ def first(n = 1)
80
+ raise ArgumentError, 'n cannot be negative' if n < 0
81
+
82
+ return first_item_after eol, count, n unless block_given?
83
+
84
+ item = eol
85
+ items_left = count
86
+
87
+ items_left.times do
88
+ break if yield next_item = item.next
89
+ item = next_item
90
+ items_left -= 1
77
91
  end
92
+
93
+ first_item_after item, items_left, n
78
94
  end
79
95
 
80
- # Access the last n item(s) in the list. When n > 1 the resulting array of
81
- # items will have their order preserved.
82
- #
83
- # When n is zero an empty array will be returned, in order to comply with
84
- # the behaviour of #first. Negative values will raise an ArgumentError.
96
+ # Access the last n item(s) in the list. The items will retain thier order.
97
+ # If a block is given each item, starting with the last in the list, will be
98
+ # yielded to it. The first item for which the block returns true and the
99
+ # n - 1 items directly preceding it will be returned.
85
100
  #
86
101
  # n - the number of items to return.
87
102
  #
88
- # Returns the last item, or an array of items if n > 1.
103
+ # Returns, for different values of n:
104
+ # n == 0) nil
105
+ # n == 1) an item if the list contains one, or nil
106
+ # n > 1) an array of between 0 and n items, depending on how many are in
107
+ # the list
89
108
 
90
109
  def last(n = 1)
91
- if n == 1
92
- eol.prev!
93
- else
94
- raise ArgumentError, 'n cannot be negative' if n < 0
95
-
96
- n = count if n > count
97
- res = Array.new n
110
+ raise ArgumentError, 'n cannot be negative' if n < 0
98
111
 
99
- return res if n == 0
112
+ return last_item_before eol, count, n unless block_given?
100
113
 
101
- item = eol.prev!
102
- loop do
103
- n -= 1
104
- res[n] = item
105
- item = item.prev
106
- end
114
+ item = eol
115
+ items_left = count
107
116
 
108
- res
117
+ items_left.times do
118
+ break if yield prev_item = item.prev
119
+ item = prev_item
120
+ items_left -= 1
109
121
  end
122
+
123
+ last_item_before item, items_left, n
110
124
  end
111
125
 
112
126
  # Overrides the Enumerable#count method when given no argument to provide a
@@ -184,21 +198,32 @@ module Linked
184
198
  # Iterates over each item in the list, either in normal or reverse order. If
185
199
  # a block is not given an enumerator is returned.
186
200
  #
187
- # reverse - flips the iteration order if true.
201
+ # reverse - flips the iteration order if true. Note that this option is
202
+ # depricated and will be removed in the next major release.
188
203
 
189
204
  def each_item(reverse: false, &block)
190
205
  if reverse
206
+ warn '[DEPRECATION] the option `reverse: true` will be removed in a future release. Please call `reverse_each_item` instead.'
191
207
  eol.before(&block)
192
208
  else
193
209
  eol.after(&block)
194
210
  end
195
211
  end
196
-
212
+
197
213
  alias each each_item
198
-
214
+
215
+ # Iterates over each item in the list in reverse order. If a block is not
216
+ # given an enumerator is returned.
217
+
218
+ def reverse_each_item(&block)
219
+ eol.before(&block)
220
+ end
221
+
222
+ alias reverse_each reverse_each_item
223
+
199
224
  # Calls #freeze on all items in the list, as well as the head and the tail
200
225
  # (eol).
201
-
226
+
202
227
  def freeze
203
228
  eol.freeze
204
229
  each_item(&:freeze)
@@ -214,15 +239,15 @@ module Linked
214
239
  def inspect(&block)
215
240
  # Get the parents inspect output
216
241
  res = [super]
217
-
242
+
218
243
  each_item do |item|
219
244
  lines = item.inspect(&block).split "\n"
220
-
245
+
221
246
  res.push (item.last? ? '└─╴' : '├─╴') + lines.shift
222
247
  padding = item.last? ? '   ' : '│  '
223
248
  lines.each { |line| res.push padding + line }
224
249
  end
225
-
250
+
226
251
  res.join("\n")
227
252
  end
228
253
 
@@ -247,5 +272,60 @@ module Linked
247
272
  private def shrink(n = 1)
248
273
  @item_count -= n
249
274
  end
275
+
276
+ # Private helper method that returns the first n items, starting just after
277
+ # item, given that there are items_left items left. The following must hold
278
+ # for the output to be valid:
279
+ # a) n > 0
280
+ # b) there are at least items_left items left
281
+ #
282
+ # item - the Item just before the item to start from
283
+ # items_left - the number of items left.
284
+ # n - the number of items to return.
285
+ #
286
+ # Returns, for different values of n:
287
+ # n == 0) nil
288
+ # n == 1) an item if items_left > 0 or nil
289
+ # n > 1) an array of items if items_left > 0 or an empty array
290
+
291
+ private def first_item_after(item, items_left, n)
292
+ # Optimize for these cases
293
+ return nil if n == 0
294
+ return item.next if n == 1
295
+
296
+ (n > items_left ? items_left : n).times.map { item = item.next }
297
+ rescue StopIteration
298
+ n > 1 ? [] : nil
299
+ end
300
+
301
+ # Private helper method that returns the last n items, ending just before
302
+ # item, given that there are items_left items left. The following must hold
303
+ # for the output to be valid:
304
+ # a) n > 0
305
+ # b) there are at least items_left items left
306
+ #
307
+ # item - the Item just after the item to start from.
308
+ # items_left - the number of items left.
309
+ # n - the number of items to return.
310
+ #
311
+ # Returns, for different values of n:
312
+ # n == 0) nil
313
+ # n == 1) an item if items_left > 0 or nil
314
+ # n > 1) an array of items if items_left > 0 or an empty array
315
+
316
+ private def last_item_before(item, items_left, n)
317
+ # Optimize for these cases
318
+ return nil if n == 0
319
+ return item.prev if n == 1
320
+
321
+ # Truncate n if it is larger than the number of items
322
+ # left
323
+ n = (n > items_left ? items_left : n)
324
+ (n - 1).downto(0).with_object(Array.new n) do |i, arr|
325
+ arr[i] = item = item.prev
326
+ end
327
+ rescue StopIteration
328
+ n > 1 ? [] : nil
329
+ end
250
330
  end
251
331
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Linked
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: linked
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Lindberg
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-07 00:00:00.000000000 Z
11
+ date: 2016-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler