sleeping_king_studios-tools 1.1.1 → 1.2.0.rc.0

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.
@@ -27,47 +27,63 @@ module SleepingKingStudios::Tools
27
27
 
28
28
  # Returns true if the object is or appears to be an Array.
29
29
  #
30
- # @param ary [Object] The object to test.
30
+ # This method checks for the method signatures of the object. An Array-like
31
+ # method will define all of the the #[], #count, and #each methods, and
32
+ # neither of the #each_key or #each_pair methods.
31
33
  #
32
- # @return [Boolean] True if the object is an Array, otherwise false.
33
- def array?(ary)
34
- return true if ary.is_a?(Array)
34
+ # @param obj [Object] the object to test.
35
+ #
36
+ # @return [Boolean] true if the object is an Array, otherwise false.
37
+ #
38
+ # @example
39
+ # ArrayTools.array?(nil)
40
+ # #=> false
41
+ #
42
+ # ArrayTools.array?([])
43
+ # #=> true
44
+ #
45
+ # ArrayTools.array?({})
46
+ # #=> false
47
+ def array?(obj)
48
+ return true if obj.is_a?(Array)
35
49
 
36
50
  ARRAY_METHODS.each do |method_name|
37
- return false unless ary.respond_to?(method_name)
51
+ return false unless obj.respond_to?(method_name)
38
52
  end
39
53
 
40
54
  OTHER_METHODS.each do |method_name|
41
- return false if ary.respond_to?(method_name)
55
+ return false if obj.respond_to?(method_name)
42
56
  end
43
57
 
44
58
  true
45
59
  end
46
60
 
61
+ # Partitions the array into matching and non-matching items.
62
+ #
47
63
  # Separates the array into two arrays, the first containing all items in the
48
64
  # original array that matches the provided block, and the second containing
49
65
  # all items in the original array that do not match the provided block.
50
66
  #
67
+ # @param ary [Array<Object>] the array to bisect.
68
+ #
69
+ # @yieldparam item [Object] an item in the array to matched.
70
+ #
71
+ # @yieldreturn [Boolean] true if the item matches the criteria, otherwise
72
+ # false.
73
+ #
74
+ # @return [Array<Array<Object>>] an array containing two arrays.
75
+ #
76
+ # @raise [ArgumentError] if the first argument is not an Array-like object,
77
+ # or if no block is given.
78
+ #
51
79
  # @example
52
80
  # selected, rejected = ArrayTools.bisect([*0...10]) { |item| item.even? }
53
81
  # selected
54
82
  # #=> [0, 2, 4, 6, 8]
55
83
  # rejected
56
84
  # #=> [1, 3, 5, 7, 9]
57
- #
58
- # @param [Array<Object>] ary The array to bisect.
59
- #
60
- # @yieldparam item [Object] An item in the array to matched.
61
- #
62
- # @yieldreturn [Boolean] True if the item matches the criteria, otherwise
63
- # false.
64
- #
65
- # @raise ArgumentError If the first argument is not an Array-like object or
66
- # if no block is given.
67
- #
68
- # @return [Array<Array<Object>>] An array containing two arrays.
69
85
  def bisect(ary)
70
- require_array! ary
86
+ require_array!(ary)
71
87
 
72
88
  raise ArgumentError, 'no block given' unless block_given?
73
89
 
@@ -81,38 +97,41 @@ module SleepingKingStudios::Tools
81
97
  [selected, rejected]
82
98
  end
83
99
 
100
+ # Counts the number of times each item or result appears in the object.
101
+ #
84
102
  # @overload count_values(ary)
85
103
  # Counts the number of times each value appears in the enumerable object.
86
104
  #
87
- # @example
88
- # ArrayTools.count_values([1, 1, 1, 2, 2, 3])
89
- # #=> { 1 => 3, 2 => 2, 3 => 1 }
90
- #
91
- # @param [Array<Object>] ary The values to count.
92
- #
93
- # @raise ArgumentError If the first argument is not an Array-like object.
105
+ # @param ary [Array<Object>] the values to count.
94
106
  #
95
107
  # @return [Hash{Object, Integer}] The number of times each value appears
96
108
  # in the enumerable object.
97
109
  #
98
- # @overload count_values(ary, &block)
99
- # Calls the block with each item and counts the number of times each
100
- # result appears.
110
+ # @raise [ArgumentError] if the first argument is not an Array-like
111
+ # object.
101
112
  #
102
113
  # @example
103
- # ArrayTools.count_values([1, 1, 1, 2, 2, 3]) { |i| i ** 2 }
104
- # #=> { 1 => 3, 4 => 2, 9 => 1 }
114
+ # ArrayTools.count_values([1, 1, 1, 2, 2, 3])
115
+ # #=> { 1 => 3, 2 => 2, 3 => 1 }
105
116
  #
106
- # @param [Array<Object>] ary The values to count.
117
+ # @overload count_values(ary, &block)
118
+ # Calls the block and counts the number of times each result appears.
107
119
  #
108
- # @yieldparam item [Object] An item in the array to matched.
120
+ # @param ary [Array<Object>] the values to count.
109
121
  #
110
- # @raise ArgumentError If the first argument is not an Array-like object.
122
+ # @yieldparam item [Object] an item in the array to matched.
111
123
  #
112
- # @return [Hash{Object, Integer}] The number of times each result
124
+ # @return [Hash{Object, Integer}] the number of times each result
113
125
  # appears.
126
+ #
127
+ # @raise [ArgumentError] if the first argument is not an Array-like
128
+ # object.
129
+ #
130
+ # @example
131
+ # ArrayTools.count_values([1, 1, 1, 2, 2, 3]) { |i| i ** 2 }
132
+ # #=> { 1 => 3, 4 => 2, 9 => 1 }
114
133
  def count_values(ary, &block)
115
- require_array! ary
134
+ require_array!(ary)
116
135
 
117
136
  ary.each.with_object({}) do |item, hsh|
118
137
  value = block_given? ? block.call(item) : item
@@ -122,32 +141,85 @@ module SleepingKingStudios::Tools
122
141
  end
123
142
  alias tally count_values
124
143
 
125
- # Creates a deep copy of the object by returning a new Array with deep
126
- # copies of each array item.
144
+ # Creates a deep copy of the object.
145
+ #
146
+ # Iterates over the array and returns a new Array with deep copies of each
147
+ # array item.
148
+ #
149
+ # @param ary [Array<Object>] the array to copy.
150
+ #
151
+ # @return [Array] the copy of the array.
127
152
  #
128
- # @param [Array<Object>] ary The array to copy.
153
+ # @raise [ArgumentError] if the first argument is not an Array-like object.
129
154
  #
130
- # @return [Array] The copy of the array.
155
+ # @see ObjectTools#deep_dup.
156
+ #
157
+ # @example
158
+ # ary = ['one', 'two', 'three']
159
+ # cpy = ArrayTools.deep_dup ary
160
+ #
161
+ # cpy << 'four'
162
+ # #=> ['one', 'two', 'three', 'four']
163
+ # ary
164
+ # #=> ['one', 'two', 'three']
165
+ #
166
+ # cpy.first.sub!(/on/, 'vu')
167
+ # cpy
168
+ # #=> ['vun', 'two', 'three', 'four']
169
+ # ary
170
+ # #=> ['one', 'two', 'three']
131
171
  def deep_dup(ary)
132
- require_array! ary
172
+ require_array!(ary)
133
173
 
134
174
  ary.map { |obj| ObjectTools.deep_dup obj }
135
175
  end
136
176
 
137
177
  # Freezes the array and performs a deep freeze on each array item.
138
178
  #
139
- # @param [Array] ary The object to freeze.
179
+ # @param ary [Array] the object to freeze.
180
+ #
181
+ # @return [Array] the frozen array.
182
+ #
183
+ # @raise [ArgumentError] if the first argument is not an Array-like object.
184
+ #
185
+ # @see ObjectTools#deep_freeze.
186
+ #
187
+ # @example
188
+ # ary = ['one', 'two', 'three']
189
+ # ArrayTools.deep_freeze ary
190
+ #
191
+ # ary.frozen?
192
+ # #=> true
193
+ # ary.first.frozen?
194
+ # #=> true
140
195
  def deep_freeze(ary)
141
- require_array! ary
196
+ require_array!(ary)
142
197
 
143
198
  ary.freeze
144
199
 
145
200
  ary.each { |obj| ObjectTools.deep_freeze obj }
146
201
  end
147
202
 
203
+ # Generates a human-readable string representation of the list items.
204
+ #
148
205
  # Accepts a list of values and returns a human-readable string of the
149
206
  # values, with the format based on the number of items.
150
207
  #
208
+ # @param ary [Array<String>] the list of values to format. Will be
209
+ # coerced to strings using #to_s.
210
+ # @param options [Hash] optional configuration hash.
211
+ # @option options [String] :last_separator the value to use to separate
212
+ # the final pair of values. Defaults to " and " (note the leading and
213
+ # trailing spaces). Will be combined with the :separator for lists of
214
+ # length 3 or greater.
215
+ # @option options [String] :separator the value to use to separate pairs
216
+ # of values before the last in lists of length 3 or greater. Defaults to
217
+ # ", " (note the trailing space).
218
+ #
219
+ # @return [String] the formatted string.
220
+ #
221
+ # @raise [ArgumentError] if the first argument is not an Array-like object.
222
+ #
151
223
  # @example With Zero Items
152
224
  # ArrayTools.humanize_list([])
153
225
  # #=> ''
@@ -170,49 +242,56 @@ module SleepingKingStudios::Tools
170
242
  # :last_separator => ' or '
171
243
  # )
172
244
  # #=> 'spam, eggs, bacon, or spam'
173
- #
174
- # @param [Array<String>] ary The list of values to format. Will be
175
- # coerced to strings using #to_s.
176
- # @param [Hash] options Optional configuration hash.
177
- # @option options [String] :last_separator The value to use to separate
178
- # the final pair of values. Defaults to " and " (note the leading and
179
- # trailing spaces). Will be combined with the :separator for lists of
180
- # length 3 or greater.
181
- # @option options [String] :separator The value to use to separate pairs
182
- # of values before the last in lists of length 3 or greater. Defaults to
183
- # ", " (note the trailing space).
184
- #
185
- # @raise ArgumentError If the first argument is not an Array-like object.
186
- #
187
- # @return [String] The formatted string.
188
- def humanize_list(ary, **options, &block)
189
- require_array! ary
245
+ def humanize_list(ary, **options, &)
246
+ require_array!(ary)
190
247
 
191
248
  return '' if ary.empty?
192
249
 
193
250
  size = ary.size
194
- ary = ary.map(&block) if block_given?
251
+ ary = ary.map(&) if block_given?
195
252
 
196
253
  return ary[0].to_s if size == 1
197
254
 
198
255
  separator, last_separator =
199
- options_for_humanize_list(size: size, **options)
256
+ options_for_humanize_list(size:, **options)
200
257
 
201
258
  return "#{ary[0]}#{last_separator}#{ary[1]}" if size == 2
202
259
 
203
260
  "#{ary[0...-1].join(separator)}#{last_separator}#{ary.last}"
204
261
  end
205
262
 
206
- # Returns true if the array is immutable, i.e. the array is frozen and each
207
- # array item is immutable.
263
+ # Checks if the array and its contents are immutable.
264
+ #
265
+ # An array is considered immutable if the array itself is frozen and each
266
+ # item in the array is immutable.
267
+ #
268
+ # @param ary [Array] the array to test.
208
269
  #
209
- # @param ary [Array] The array to test.
270
+ # @return [Boolean] true if the array is immutable, otherwise false.
210
271
  #
211
- # @return [Boolean] True if the array is immutable, otherwise false.
272
+ # @raise [ArgumentError] if the first argument is not an Array-like object.
273
+ #
274
+ # @see ArrayTools#mutable?
212
275
  #
213
276
  # @see ObjectTools#immutable?
277
+ #
278
+ # @example
279
+ # ArrayTools.immutable?([1, 2, 3])
280
+ # #=> false
281
+ #
282
+ # ArrayTools.immutable?([1, 2, 3].freeze)
283
+ # #=> true
284
+ #
285
+ # ArrayTools.immutable?([+'ichi', +'ni', +'san'])
286
+ # #=> false
287
+ #
288
+ # ArrayTools.immutable?([+'ichi', +'ni', +'san'].freeze)
289
+ # #=> false
290
+ #
291
+ # ArrayTools.immutable?(['ichi', 'ni', 'san'].freeze)
292
+ # #=> true
214
293
  def immutable?(ary)
215
- require_array! ary
294
+ require_array!(ary)
216
295
 
217
296
  return false unless ary.frozen?
218
297
 
@@ -221,21 +300,32 @@ module SleepingKingStudios::Tools
221
300
  true
222
301
  end
223
302
 
224
- # Returns true if the array is mutable.
303
+ # Checks if the array or any of its contents are mutable.
304
+ #
305
+ # @param ary [Array] the array to test.
225
306
  #
226
- # @param ary [Array] The array to test.
307
+ # @return [Boolean] true if the array or any of its items are mutable,
308
+ # otherwise false.
227
309
  #
228
- # @return [Boolean] True if the array is mutable, otherwise false.
310
+ # @raise [ArgumentError] if the first argument is not an Array-like object.
229
311
  #
230
312
  # @see #immutable?
231
313
  def mutable?(ary)
232
314
  !immutable?(ary)
233
315
  end
234
316
 
235
- # Accepts an array, a start value, a number of items to delete, and zero or
236
- # more items to insert at that index. Deletes the specified number of items,
237
- # then inserts the given items at the index and returns the array of deleted
238
- # items.
317
+ # Replaces a range of items in the array with the given items.
318
+ #
319
+ # @param ary [Array<Object>] the array to splice.
320
+ # @param start [Integer] the starting index to delete or insert values from
321
+ # or into. If negative, counts backward from the end of the array.
322
+ # @param delete_count [Integer] the number of items to delete.
323
+ # @param insert [Array<Object>] the items to insert, if any.
324
+ #
325
+ # @return [Array<Object>] the deleted items, or an empty array if no items
326
+ # were deleted.
327
+ #
328
+ # @raise [ArgumentError] if the first argument is not an Array-like object.
239
329
  #
240
330
  # @example Deleting items from an Array
241
331
  # values = %w(katana wakizashi tachi daito shoto)
@@ -257,21 +347,10 @@ module SleepingKingStudios::Tools
257
347
  # #=> ['crossbow']
258
348
  # values
259
349
  # #=> ['shortbow', 'longbow', 'arbalest', 'chu-ko-nu']
260
- #
261
- # @param [Array<Object>] ary The array to splice.
262
- # @param [Integer] start The starting index to delete or insert values from
263
- # or into. If negative, counts backward from the end of the array.
264
- # @param [Integer] delete_count The number of items to delete.
265
- # @param [Array<Object>] insert The items to insert, if any.
266
- #
267
- # @raise ArgumentError If the first argument is not an Array-like object.
268
- #
269
- # @return [Array<Object>] The deleted items, or an empty array if no items
270
- # were deleted.
271
350
  def splice(ary, start, delete_count, *insert)
272
- require_array! ary
351
+ require_array!(ary)
273
352
 
274
- start = start.negative? ? start + ary.count : start
353
+ start += ary.count if start.negative?
275
354
  range = start...(start + delete_count)
276
355
  deleted = ary[range]
277
356