xqsr3 0.39.1 → 0.39.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/examples/count_word_frequencies.rb +2 -0
  3. data/lib/xqsr3/array_utilities/join_with_or.rb +50 -53
  4. data/lib/xqsr3/command_line_utilities/map_option_string.rb +66 -69
  5. data/lib/xqsr3/containers/frequency_map.rb +408 -394
  6. data/lib/xqsr3/containers/multi_map.rb +464 -446
  7. data/lib/xqsr3/conversion/bool_parser.rb +49 -54
  8. data/lib/xqsr3/conversion/integer_parser.rb +84 -89
  9. data/lib/xqsr3/diagnostics/exception_utilities.rb +127 -132
  10. data/lib/xqsr3/diagnostics/exceptions/with_cause.rb +98 -102
  11. data/lib/xqsr3/diagnostics/inspect_builder.rb +83 -84
  12. data/lib/xqsr3/extensions/array/join_with_or.rb +2 -1
  13. data/lib/xqsr3/extensions/enumerable/collect_with_index.rb +1 -4
  14. data/lib/xqsr3/extensions/enumerable/unique.rb +1 -4
  15. data/lib/xqsr3/extensions/hash/deep_transform.rb +1 -0
  16. data/lib/xqsr3/extensions/hash/except.rb +1 -1
  17. data/lib/xqsr3/extensions/hash/has_match.rb +3 -2
  18. data/lib/xqsr3/extensions/hash/match.rb +3 -2
  19. data/lib/xqsr3/extensions/integer/to_s_grp.rb +1 -4
  20. data/lib/xqsr3/extensions/io/writelines.rb +4 -7
  21. data/lib/xqsr3/extensions/kernel/integer.rb +7 -9
  22. data/lib/xqsr3/extensions/kernel/raise_with_options.rb +1 -3
  23. data/lib/xqsr3/extensions/string/ends_with.rb +1 -0
  24. data/lib/xqsr3/extensions/string/map_option_string.rb +1 -0
  25. data/lib/xqsr3/extensions/string/nil_if_empty.rb +1 -0
  26. data/lib/xqsr3/extensions/string/nil_if_whitespace.rb +1 -0
  27. data/lib/xqsr3/extensions/string/quote_if.rb +1 -0
  28. data/lib/xqsr3/extensions/string/starts_with.rb +1 -0
  29. data/lib/xqsr3/extensions/string/to_bool.rb +1 -0
  30. data/lib/xqsr3/extensions/string/to_symbol.rb +1 -0
  31. data/lib/xqsr3/extensions/string/truncate.rb +1 -0
  32. data/lib/xqsr3/extensions/test/unit/assert_eql.rb +11 -9
  33. data/lib/xqsr3/extensions/test/unit/assert_false.rb +10 -8
  34. data/lib/xqsr3/extensions/test/unit/assert_not.rb +10 -8
  35. data/lib/xqsr3/extensions/test/unit/assert_not_eql.rb +11 -9
  36. data/lib/xqsr3/extensions/test/unit/assert_raise_with_message.rb +58 -55
  37. data/lib/xqsr3/extensions/test/unit/assert_subclass_of.rb +11 -9
  38. data/lib/xqsr3/extensions/test/unit/assert_superclass_of.rb +11 -9
  39. data/lib/xqsr3/extensions/test/unit/assert_true.rb +10 -8
  40. data/lib/xqsr3/extensions/test/unit/assert_type_has_instance_methods.rb +39 -37
  41. data/lib/xqsr3/hash_utilities/deep_transform.rb +63 -67
  42. data/lib/xqsr3/hash_utilities/key_matching.rb +72 -76
  43. data/lib/xqsr3/internal_/test_unit_version_.rb +10 -8
  44. data/lib/xqsr3/io/writelines.rb +12 -12
  45. data/lib/xqsr3/quality/parameter_checking.rb +406 -411
  46. data/lib/xqsr3/string_utilities/ends_with.rb +60 -64
  47. data/lib/xqsr3/string_utilities/nil_if_empty.rb +31 -35
  48. data/lib/xqsr3/string_utilities/nil_if_whitespace.rb +32 -36
  49. data/lib/xqsr3/string_utilities/quote_if.rb +48 -57
  50. data/lib/xqsr3/string_utilities/starts_with.rb +60 -64
  51. data/lib/xqsr3/string_utilities/to_symbol.rb +77 -81
  52. data/lib/xqsr3/string_utilities/truncate.rb +56 -60
  53. data/lib/xqsr3/version.rb +2 -2
  54. data/test/performance/frequency_map.rb +3 -0
  55. data/test/scratch/test_assert_raise_with_message.rb +2 -0
  56. data/test/unit/array_utilities/tc_join_with_or.rb +3 -1
  57. data/test/unit/command_line_utilities/tc_map_option_string.rb +3 -0
  58. data/test/unit/containers/tc_frequency_map.rb +5 -2
  59. data/test/unit/containers/tc_multi_map.rb +3 -0
  60. data/test/unit/conversion/tc_integer_parser.rb +18 -17
  61. data/test/unit/conversion/tc_to_bool.rb +2 -0
  62. data/test/unit/diagnostics/exceptions/tc_with_cause.rb +7 -5
  63. data/test/unit/diagnostics/tc_exception_utilities.rb +2 -0
  64. data/test/unit/extensions/enumerable/tc_collect_with_index.rb +2 -0
  65. data/test/unit/extensions/enumerable/tc_detect_map.rb +3 -2
  66. data/test/unit/extensions/enumerable/tc_unique.rb +2 -0
  67. data/test/unit/extensions/hash/tc_deep_transform.rb +2 -0
  68. data/test/unit/extensions/hash/tc_except.rb +3 -1
  69. data/test/unit/extensions/hash/tc_hash.rb +1 -0
  70. data/test/unit/extensions/hash/tc_slice.rb +2 -0
  71. data/test/unit/extensions/integer/tc_to_s_grp.rb +2 -0
  72. data/test/unit/extensions/io/tc_writelines.rb +86 -0
  73. data/test/unit/extensions/kernel/tc_integer.rb +10 -9
  74. data/test/unit/extensions/kernel/tc_raise_with_options.rb +2 -0
  75. data/test/unit/extensions/object/tc_inspect.rb +15 -13
  76. data/test/unit/extensions/string/tc_bool.tb +2 -0
  77. data/test/unit/extensions/string/tc_ends_with.rb +2 -0
  78. data/test/unit/extensions/string/tc_map_option_string.rb +2 -0
  79. data/test/unit/extensions/string/tc_nil_if_empty.rb +2 -0
  80. data/test/unit/extensions/string/tc_nil_if_whitespace.rb +2 -0
  81. data/test/unit/extensions/string/tc_quote_if.rb +2 -0
  82. data/test/unit/extensions/string/tc_starts_with.rb +2 -0
  83. data/test/unit/extensions/string/tc_to_symbol.rb +2 -0
  84. data/test/unit/extensions/string/tc_truncate.rb +2 -0
  85. data/test/unit/extensions/test/unit/tc_assert_raise_with_message.rb +2 -0
  86. data/test/unit/extensions/test/unit/tc_assert_subclass_of.rb +2 -0
  87. data/test/unit/extensions/test/unit/tc_assert_superclass_of.rb +2 -0
  88. data/test/unit/hash_utilities/tc_has_match.rb +1 -0
  89. data/test/unit/hash_utilities/tc_match.rb +1 -0
  90. data/test/unit/io/tc_writelines.rb +63 -0
  91. data/test/unit/quality/tc_parameter_checking.rb +1 -0
  92. data/test/unit/string_utilities/tc_truncate.rb +2 -0
  93. data/test/unit/tc_version.rb +2 -0
  94. metadata +3 -3
@@ -5,7 +5,7 @@
5
5
  # Purpose: FrequencyMap container
6
6
  #
7
7
  # Created: 28th January 2005
8
- # Updated: 29th March 2024
8
+ # Updated: 12th April 2024
9
9
  #
10
10
  # Home: http://github.com/synesissoftware/xqsr3
11
11
  #
@@ -47,572 +47,586 @@
47
47
 
48
48
  require 'xqsr3/diagnostics/inspect_builder'
49
49
 
50
+
50
51
  =begin
51
52
  =end
52
53
 
53
54
  module Xqsr3
54
55
  module Containers
55
56
 
56
- # Hash-like class that counts, as the map's values, the frequencies of
57
- # elements, as the map's keys
58
- class FrequencyMap
57
+ # Hash-like class that counts, as the map's values, the frequencies of
58
+ # elements, as the map's keys
59
+ class FrequencyMap
60
+
61
+ include Enumerable
62
+ include ::Xqsr3::Diagnostics::InspectBuilder
63
+
64
+ # Class that provides a Hash[]-like syntax as follows:
65
+ #
66
+ # fm = FrequencyMap::ByElement[ 'abc', 'def', 'abc', :x, 'x', :y ]
67
+ #
68
+ # fm.empty? # => false
69
+ # fm.size # => 5
70
+ # fm.count # => 6
71
+ # fm['abc'] # => 2
72
+ # fm['def'] # => 1
73
+ # fm['ghi'] # => 0
74
+ # fm['x'] # => 1
75
+ # fm['y'] # => 0
76
+ # fm['z'] # => 0
77
+ # fm[:x] # => 1
78
+ # fm[:y] # => 1
79
+ # fm[:z] # => 0
80
+ ByElement = Class.new do
81
+
82
+ # Create an instance of Xqsr3::FrequencyMap from an array
83
+ def self.[] *args
84
+
85
+ fm = FrequencyMap.new
86
+
87
+ args.each { |el| fm << el }
88
+
89
+ fm
90
+ end
59
91
 
60
- include Enumerable
61
- include ::Xqsr3::Diagnostics::InspectBuilder
92
+ private_class_method :new
93
+ end
62
94
 
63
- # Class that provides a Hash[]-like syntax as follows:
64
- #
65
- # fm = FrequencyMap::ByElement[ 'abc', 'def', 'abc', :x, 'x', :y ]
66
- #
67
- # fm.empty? # => false
68
- # fm.size # => 5
69
- # fm.count # => 6
70
- # fm['abc'] # => 2
71
- # fm['def'] # => 1
72
- # fm['ghi'] # => 0
73
- # fm['x'] # => 1
74
- # fm['y'] # => 0
75
- # fm['z'] # => 0
76
- # fm[:x] # => 1
77
- # fm[:y] # => 1
78
- # fm[:z] # => 0
79
- ByElement = Class.new do
80
-
81
- # Create an instance of Xqsr3::FrequencyMap from an array
95
+ # Creates an instance from the given arguments
82
96
  def self.[] *args
83
97
 
84
- fm = FrequencyMap.new
85
-
86
- args.each { |el| fm << el }
98
+ return self.new if 0 == args.length
87
99
 
88
- fm
89
- end
100
+ if 1 == args.length
90
101
 
91
- private_class_method :new
92
- end
102
+ arg = args[0]
93
103
 
94
- # Creates an instance from the given arguments
95
- def self.[] *args
104
+ case arg
105
+ when ::NilClass
96
106
 
97
- return self.new if 0 == args.length
107
+ return self.new
108
+ when ::Hash
98
109
 
99
- if 1 == args.length
110
+ fm = self.new
111
+ arg.each do |k, v|
100
112
 
101
- arg = args[0]
113
+ fm.store k, v
114
+ end
115
+ return fm
116
+ when ::Array
102
117
 
103
- case arg
104
- when ::NilClass
118
+ # accepted forms:
119
+ #
120
+ # 1. Empty array
121
+ # 2. Array exclusively of two-element arrays
122
+ # 3. Array of even number of elements and at every odd index is an integer
105
123
 
106
- return self.new
107
- when ::Hash
124
+ # 1. Empty array
108
125
 
109
- fm = self.new
110
- arg.each do |k, v|
126
+ return self.new if arg.empty?
111
127
 
112
- fm.store k, v
113
- end
114
- return fm
115
- when ::Array
128
+ # 2. Array exclusively of two-element arrays
116
129
 
117
- # accepted forms:
118
- #
119
- # 1. Empty array
120
- # 2. Array exclusively of two-element arrays
121
- # 3. Array of even number of elements and at every odd index is an integer
130
+ if arg.all? { |el| ::Array === el && 2 == el.size }
122
131
 
123
- # 1. Empty array
132
+ return self.[](::Hash.[]([ *arg ]))
133
+ end
124
134
 
125
- return self.new if arg.empty?
135
+ # 3. Array of even number of elements and at every odd index is an integer
126
136
 
127
- # 2. Array exclusively of two-element arrays
137
+ if (0 == (arg.size % 2)) && arg.each_with_index.select { |el, index| 1 == (index % 2) }.map(&:first).all? { |el| el.kind_of? ::Integer }
128
138
 
129
- if arg.all? { |el| ::Array === el && 2 == el.size }
139
+ return self.[](::Hash.[](*arg))
140
+ end
130
141
 
131
- return self.[](::Hash.[]([ *arg ]))
132
- end
133
142
 
134
- # 3. Array of even number of elements and at every odd index is an integer
143
+ raise ArgumentError, "array parameter not in an accepted form for subscript initialisation"
144
+ else
135
145
 
136
- if (0 == (arg.size % 2)) && arg.each_with_index.select { |el, index| 1 == (index % 2) }.map(&:first).all? { |el| el.kind_of? ::Integer }
146
+ return self.[] arg.to_hash if arg.respond_to? :to_hash
137
147
 
138
- return self.[](::Hash.[](*arg))
148
+ raise TypeError, "given argument is neither a #{::Hash} nor an #{::Array} and does not respond to the to_hash method"
139
149
  end
140
150
 
141
-
142
- raise ArgumentError, "array parameter not in an accepted form for subscript initialisation"
143
151
  else
144
152
 
145
- return self.[] arg.to_hash if arg.respond_to? :to_hash
153
+ # treat all other argument permutations as having passed in an array
146
154
 
147
- raise TypeError, "given argument is neither a #{::Hash} nor an #{::Array} and does not respond to the to_hash method"
155
+ return self.[] [ *args ]
148
156
  end
149
-
150
- else
151
-
152
- # treat all other argument permutations as having passed in an array
153
-
154
- return self.[] [ *args ]
155
157
  end
156
- end
157
158
 
158
- # Initialises an instance
159
- def initialize
159
+ # Initialises an instance
160
+ def initialize
160
161
 
161
- @elements = {}
162
- @count = 0
163
- end
162
+ @elements = {}
163
+ @count = 0
164
+ end
164
165
 
165
- # Pushes an element into the map, assigning it an initial count of 1
166
- #
167
- # * *Parameters:*
168
- # - +key+ The element to insert
169
- def << key
166
+ # Pushes an element into the map, assigning it an initial count of 1
167
+ #
168
+ # === Signature
169
+ #
170
+ # * *Parameters:*
171
+ # - +key+ The element to insert;
172
+ def << key
170
173
 
171
- push key, 1
172
- end
174
+ push key, 1
175
+ end
173
176
 
174
- # Compares the instance for equality against +rhs+
175
- #
176
- # * *Parameters:*
177
- # - +rhs+ (+nil+, +::Hash+, +FrequencyMap+) The instance to compare against
178
- #
179
- # * *Exceptions:*
180
- # - +::TypeError+ if +rhs+ is not of the required type(s)
181
- def == rhs
177
+ # Compares the instance for equality against +rhs+
178
+ #
179
+ # === Signature
180
+ #
181
+ # * *Parameters:*
182
+ # - +rhs+ (+nil+, +Hash+, +FrequencyMap+) The instance to compare against;
183
+ #
184
+ # === Exceptions
185
+ # - +TypeError+ if +rhs+ is not of the required type(s);
186
+ def == rhs
187
+
188
+ case rhs
189
+ when ::NilClass
182
190
 
183
- case rhs
184
- when ::NilClass
191
+ return false
192
+ when ::Hash
185
193
 
186
- return false
187
- when ::Hash
194
+ return rhs.size == @elements.size && rhs == @elements
195
+ when self.class
188
196
 
189
- return rhs.size == @elements.size && rhs == @elements
190
- when self.class
197
+ return rhs.count == self.count && rhs == @elements
198
+ else
191
199
 
192
- return rhs.count == self.count && rhs == @elements
193
- else
200
+ raise TypeError, "can compare #{self.class} only to instances of #{self.class} and #{::Hash}, but #{rhs.class} given"
201
+ end
194
202
 
195
- raise TypeError, "can compare #{self.class} only to instances of #{self.class} and #{::Hash}, but #{rhs.class} given"
203
+ false
196
204
  end
197
205
 
198
- false
199
- end
200
-
201
- # Obtains the count for a given key, or +nil+ if the key does not exist
202
- #
203
- # * *Parameters:*
204
- # - +key+ The key to lookup
205
- def [] key
206
-
207
- @elements[key] || 0
208
- end
209
-
210
- # Assigns a key and a count
211
- #
212
- # * *Parameters:*
213
- # - +key+ The key to lookup
214
- # - +count+ (::Integer) The count to lookup
215
- #
216
- # * *Exceptions:*
217
- # - +::TypeError+ if +count+ is not an +::Integer+
218
- def []= key, count
206
+ # Obtains the count for a given key, or +nil+ if the key does not exist
207
+ #
208
+ # === Signature
209
+ #
210
+ # * *Parameters:*
211
+ # - +key+ The key to lookup
212
+ def [] key
219
213
 
220
- raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
214
+ @elements[key] || 0
215
+ end
221
216
 
222
- store key, count
223
- end
217
+ # Assigns a key and a count
218
+ #
219
+ # === Signature
220
+ #
221
+ # * *Parameters:*
222
+ # - +key+ The key to lookup;
223
+ # - +count+ (+Integer+) The count to lookup;
224
+ #
225
+ # === Exceptions
226
+ # - +TypeError+ if +count+ is not an +Integer+
227
+ def []= key, count
228
+
229
+ raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
230
+
231
+ store key, count
232
+ end
224
233
 
225
- # Searches the instance comparing each element with +key+, returning the
226
- # count if found, or +nil+ if not
227
- def assoc key
234
+ # Searches the instance comparing each element with +key+, returning the
235
+ # count if found, or +nil+ if not
236
+ def assoc key
228
237
 
229
- @elements.assoc key
230
- end
238
+ @elements.assoc key
239
+ end
231
240
 
232
- # Removes all elements from the instance
233
- def clear
241
+ # Removes all elements from the instance
242
+ def clear
234
243
 
235
- @elements.clear
236
- @count = 0
237
- end
244
+ @elements.clear
245
+ @count = 0
246
+ end
238
247
 
239
- # The total number of instances recorded
240
- def count
248
+ # The total number of instances recorded
249
+ def count
241
250
 
242
- @count
243
- end
251
+ @count
252
+ end
244
253
 
245
- # Obtains the default value of the instance, which will always be +nil+
246
- def default
254
+ # Obtains the default value of the instance, which will always be +nil+
255
+ def default
247
256
 
248
- @elements.default
249
- end
257
+ @elements.default
258
+ end
250
259
 
251
- # Deletes the element with the given +key+ and its counts
252
- #
253
- # * *Parameters:*
254
- # - +key+ The key to delete
255
- def delete key
260
+ # Deletes the element with the given +key+ and its counts
261
+ #
262
+ # === Signature
263
+ #
264
+ # * *Parameters:*
265
+ # - +key+ The key to delete
266
+ def delete key
256
267
 
257
- key_count = @elements.delete key
268
+ key_count = @elements.delete key
258
269
 
259
- @count -= key_count if key_count
260
- end
270
+ @count -= key_count if key_count
271
+ end
261
272
 
262
- # Duplicates the instance
263
- def dup
273
+ # Duplicates the instance
274
+ def dup
264
275
 
265
- fm = self.class.new
276
+ fm = self.class.new
266
277
 
267
- fm.merge! self
268
- end
278
+ fm.merge! self
279
+ end
269
280
 
270
- # Calls _block_ once for each element in the instance, passing the element
271
- # and its frequency as parameters. If no block is provided, an enumerator
272
- # is returned
273
- def each
281
+ # Calls _block_ once for each element in the instance, passing the element
282
+ # and its frequency as parameters. If no block is provided, an enumerator
283
+ # is returned
284
+ def each
274
285
 
275
- return @elements.each unless block_given?
286
+ return @elements.each unless block_given?
276
287
 
277
- @elements.each do |k, v|
288
+ @elements.each do |k, v|
278
289
 
279
- yield k, v
290
+ yield k, v
291
+ end
280
292
  end
281
- end
282
293
 
283
- # Enumerates each entry pair - element + frequency - in key order
284
- #
285
- # Note: this method is more expensive than +each+ because an array of
286
- # keys must be created and sorted from which enumeration is directed
287
- def each_by_key
294
+ # Enumerates each entry pair - element + frequency - in key order
295
+ #
296
+ # Note: this method is more expensive than +each+ because an array of
297
+ # keys must be created and sorted from which enumeration is directed
298
+ def each_by_key
288
299
 
289
- sorted_elements = @elements.sort { |a, b| a[0] <=> b[0] }
300
+ sorted_elements = @elements.sort { |a, b| a[0] <=> b[0] }
290
301
 
291
- return sorted_elements.each unless block_given?
302
+ return sorted_elements.each unless block_given?
292
303
 
293
- sorted_elements.each do |k, v|
304
+ sorted_elements.each do |k, v|
294
305
 
295
- yield k, v
306
+ yield k, v
307
+ end
296
308
  end
297
- end
298
309
 
299
- # Enumerates each entry pair - element + frequency - in descending
300
- # order of frequency
301
- #
302
- # Note: this method is expensive, as it must create a new dictionary
303
- # and map all entries into it in order to achieve the ordering
304
- def each_by_frequency
310
+ # Enumerates each entry pair - element + frequency - in descending
311
+ # order of frequency
312
+ #
313
+ # Note: this method is expensive, as it must create a new dictionary
314
+ # and map all entries into it in order to achieve the ordering
315
+ def each_by_frequency
305
316
 
306
- ar = @elements.to_a.sort { |a, b| b[1] <=> a[1] }
317
+ ar = @elements.to_a.sort { |a, b| b[1] <=> a[1] }
307
318
 
308
- return ar.each unless block_given?
319
+ return ar.each unless block_given?
309
320
 
310
- ar.each do |k, v|
321
+ ar.each do |k, v|
311
322
 
312
- yield k, v
323
+ yield k, v
324
+ end
313
325
  end
314
- end
315
326
 
316
- # Calls _block_ once for each element in the instance, passing the
317
- # element. If no block is provided, an enumerator is returned
318
- def each_key
327
+ # Calls _block_ once for each element in the instance, passing the
328
+ # element. If no block is provided, an enumerator is returned
329
+ def each_key
319
330
 
320
- return @elements.each_key unless block_given?
331
+ return @elements.each_key unless block_given?
321
332
 
322
- keys.each do |element|
333
+ keys.each do |element|
323
334
 
324
- yield element
335
+ yield element
336
+ end
325
337
  end
326
- end
327
338
 
328
- alias each_pair each
339
+ alias each_pair each
329
340
 
330
- # Calls _block_ once for each element in the instance, passing the
331
- # count. If no block is provided, an enumerator is returned
332
- def each_value
341
+ # Calls _block_ once for each element in the instance, passing the
342
+ # count. If no block is provided, an enumerator is returned
343
+ def each_value
333
344
 
334
- return @elements.each_value unless block_given?
345
+ return @elements.each_value unless block_given?
335
346
 
336
- keys.each do |element|
347
+ keys.each do |element|
337
348
 
338
- yield @elements[element]
349
+ yield @elements[element]
350
+ end
339
351
  end
340
- end
341
352
 
342
- # Returns +true+ if instance contains no elements; +false+ otherwise
343
- def empty?
353
+ # Returns +true+ if instance contains no elements; +false+ otherwise
354
+ def empty?
344
355
 
345
- 0 == size
346
- end
356
+ 0 == size
357
+ end
347
358
 
348
- # Returns +true+ if +rhs+ is an instance of +FrequencyMap+ and contains
349
- # the same elements and their counts; +false+ otherwise
350
- def eql? rhs
359
+ # Returns +true+ if +rhs+ is an instance of +FrequencyMap+ and contains
360
+ # the same elements and their counts; +false+ otherwise
361
+ def eql? rhs
351
362
 
352
- case rhs
353
- when self.class
354
- return self == rhs
355
- else
356
- return false
363
+ case rhs
364
+ when self.class
365
+ return self == rhs
366
+ else
367
+ return false
368
+ end
357
369
  end
358
- end
359
370
 
360
- # Returns the count from the instance for the given element +key+. If
361
- # +key+ cannot be found, there are several options: with no other
362
- # arguments, it will raise a +::KeyError+ exception; if +default+ is
363
- # given, then that will be returned; if the optional code block is
364
- # specified, then that will be run and its result returned
365
- def fetch key, default = nil, &block
371
+ # Returns the count from the instance for the given element +key+. If
372
+ # +key+ cannot be found, there are several options: with no other
373
+ # arguments, it will raise a +KeyError+ exception; if +default+ is
374
+ # given, then that will be returned; if the optional code block is
375
+ # specified, then that will be run and its result returned
376
+ def fetch key, default = nil, &block
366
377
 
367
- case default
368
- when ::NilClass, ::Integer
369
- ;
370
- else
371
- raise TypeError, "default parameter ('#{default}') must be of type #{::Integer}, but was of type #{default.class}"
372
- end
378
+ case default
379
+ when ::NilClass, ::Integer
380
+ ;
381
+ else
382
+ raise TypeError, "default parameter ('#{default}') must be of type #{::Integer}, but was of type #{default.class}"
383
+ end
373
384
 
374
- unless @elements.has_key? key
385
+ unless @elements.has_key? key
375
386
 
376
- return default unless default.nil?
387
+ return default unless default.nil?
377
388
 
378
- if block_given?
389
+ if block_given?
379
390
 
380
- case block.arity
381
- when 0
382
- return yield
383
- when 1
384
- return yield key
385
- else
386
- raise ArgumentError, "given block must take a single parameter - #{block.arity} given"
391
+ case block.arity
392
+ when 0
393
+ return yield
394
+ when 1
395
+ return yield key
396
+ else
397
+ raise ArgumentError, "given block must take a single parameter - #{block.arity} given"
398
+ end
387
399
  end
400
+
401
+ raise KeyError, "given key '#{key}' (#{key.class}) does not exist"
388
402
  end
389
403
 
390
- raise KeyError, "given key '#{key}' (#{key.class}) does not exist"
404
+ @elements[key]
391
405
  end
392
406
 
393
- @elements[key]
394
- end
395
-
396
- # Returns the equivalent flattened form of the instance
397
- def flatten
407
+ # Returns the equivalent flattened form of the instance
408
+ def flatten
398
409
 
399
- @elements.flatten
400
- end
410
+ @elements.flatten
411
+ end
401
412
 
402
- # Returns +true+ if an element with the given +key+ is in the map; +false+
403
- # otherwise
404
- def has_key? key
413
+ # Returns +true+ if an element with the given +key+ is in the map; +false+
414
+ # otherwise
415
+ def has_key? key
405
416
 
406
- @elements.has_key? key
407
- end
417
+ @elements.has_key? key
418
+ end
408
419
 
409
- # Returns +true+ if an element with a count of the given +value+ is in the
410
- # map; +false+ otherwise
411
- #
412
- # * *Parameters:*
413
- # - +value+ (Integer) The value of the count for which to search
414
- #
415
- # * *Exceptions:*
416
- # - +::TypeError+ if +value+ is not an Integer
417
- def has_value? value
420
+ # Returns +true+ if an element with a count of the given +value+ is in the
421
+ # map; +false+ otherwise
422
+ #
423
+ # === Signature
424
+ #
425
+ # * *Parameters:*
426
+ # - +value+ (Integer) The value of the count for which to search;
427
+ #
428
+ # === Exceptions
429
+ # - +TypeError+ if +value+ is not an Integer;
430
+ def has_value? value
431
+
432
+ case value
433
+ when ::NilClass, ::Integer
434
+ ;
435
+ else
436
+ raise TypeError, "parameter ('#{value}') must be of type #{::Integer}, but was of type #{value.class}"
437
+ end
418
438
 
419
- case value
420
- when ::NilClass, ::Integer
421
- ;
422
- else
423
- raise TypeError, "parameter ('#{value}') must be of type #{::Integer}, but was of type #{value.class}"
439
+ @elements.has_value? value
424
440
  end
425
441
 
426
- @elements.has_value? value
427
- end
442
+ # A hash-code for this instance
443
+ def hash
428
444
 
429
- # A hash-code for this instance
430
- def hash
431
-
432
- @elements.hash
433
- end
445
+ @elements.hash
446
+ end
434
447
 
435
- alias include? has_key?
448
+ alias include? has_key?
436
449
 
437
- # A diagnostics string form of the instance
438
- def inspect
450
+ # A diagnostics string form of the instance
451
+ def inspect
439
452
 
440
- make_inspect show_fields: true
441
- end
453
+ make_inspect show_fields: true
454
+ end
442
455
 
443
- # def keep_if
444
- #
445
- # @elements.keep_if
446
- # end
456
+ # def keep_if
457
+ #
458
+ # @elements.keep_if
459
+ # end
447
460
  =begin
448
461
  =end
449
462
 
450
- # Returns the element that has the given count, or +nil+ if none found
451
- #
452
- # * *Parameters:*
453
- # - +count+ (::Integer) The count to lookup
454
- #
455
- # * *Exceptions:*
456
- # - +::TypeError+ if +count+ is not of the required type(s)
457
- def key count
463
+ # Returns the element that has the given count, or +nil+ if none found
464
+ #
465
+ # === Signature
466
+ #
467
+ # * *Parameters:*
468
+ # - +count+ (+Integer+) The count to lookup;
469
+ #
470
+ # === Exceptions
471
+ # - +TypeError+ if +count+ is not of the required type(s);
472
+ def key count
458
473
 
459
- raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
474
+ raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
460
475
 
461
- @elements.key count
462
- end
476
+ @elements.key count
477
+ end
463
478
 
464
- alias key? has_key?
479
+ alias key? has_key?
465
480
 
466
- # An array of the elements only
467
- def keys
481
+ # An array of the elements only
482
+ def keys
468
483
 
469
- @elements.keys
470
- end
484
+ @elements.keys
485
+ end
471
486
 
472
- # The number of elements in the map
473
- def length
487
+ # The number of elements in the map
488
+ def length
474
489
 
475
- @elements.length
476
- end
490
+ @elements.length
491
+ end
477
492
 
478
- alias member? has_key?
493
+ alias member? has_key?
479
494
 
480
- # Returns a new instance containing a merging of the current instance and
481
- # the +fm+ instance
482
- #
483
- # NOTE: where any element is found in both merging instances the count
484
- # will be a combination of the two counts
485
- def merge fm
495
+ # Returns a new instance containing a merging of the current instance and
496
+ # the +fm+ instance
497
+ #
498
+ # NOTE: where any element is found in both merging instances the count
499
+ # will be a combination of the two counts
500
+ def merge fm
486
501
 
487
- raise TypeError, "parameter must be an instance of type #{self.class}" unless fm.instance_of? self.class
502
+ raise TypeError, "parameter must be an instance of type #{self.class}" unless fm.instance_of? self.class
488
503
 
489
- fm_new = self.class.new
504
+ fm_new = self.class.new
490
505
 
491
- fm_new.merge! self
492
- fm_new.merge! fm
506
+ fm_new.merge! self
507
+ fm_new.merge! fm
493
508
 
494
- fm_new
495
- end
509
+ fm_new
510
+ end
496
511
 
497
- # Merges the contents of +fm+ into the current instance
498
- #
499
- # NOTE: where any element is found in both merging instances the count
500
- # will be a combination of the two counts
501
- def merge! fm
512
+ # Merges the contents of +fm+ into the current instance
513
+ #
514
+ # NOTE: where any element is found in both merging instances the count
515
+ # will be a combination of the two counts
516
+ def merge! fm
502
517
 
503
- fm.each do |k, v|
518
+ fm.each do |k, v|
504
519
 
505
- if not @elements.has_key? k
520
+ if not @elements.has_key? k
506
521
 
507
- @elements[k] = v
508
- else
522
+ @elements[k] = v
523
+ else
509
524
 
510
- @elements[k] += v
525
+ @elements[k] += v
526
+ end
527
+ @count += v
511
528
  end
512
- @count += v
529
+
530
+ self
513
531
  end
514
532
 
515
- self
516
- end
533
+ # Pushes the +element+ and +count+. If the +element+ already exists,
534
+ # +count+ will be added to the existing count; otherwise it will be
535
+ # +count+
536
+ #
537
+ # === Signature
538
+ #
539
+ # * *Parameters:*
540
+ # - +key+ The element key;
541
+ # - +count+ (+Integer+) The count by which to adjust;
542
+ #
543
+ # === Exceptions
544
+ # - +RangeError+ raised if the value of +count+ results in a negative count for the given element;
545
+ # - +TypeError+ if +count+ is not an +Integer+;
546
+ def push key, count = 1
517
547
 
518
- # Pushes the +element+ and +count+. If the +element+ already exists,
519
- # +count+ will be added to the existing count; otherwise it will be
520
- # +count+
521
- #
522
- # === Signature
523
- #
524
- # * *Parameters:*
525
- # - +key+ The element key
526
- # - +count+ (Integer) The count by which to adjust
527
- #
528
- # === Exceptions
529
- # - +::RangeError+ raised if the value of +count+ results in a negative count for the given element
530
- # - +::TypeError+ if +count+ is not an +::Integer+
531
- def push key, count = 1
548
+ raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
532
549
 
533
- raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
550
+ initial_count = @elements[key] || 0
551
+ resulting_count = initial_count + count
534
552
 
535
- initial_count = @elements[key] || 0
536
- resulting_count = initial_count + count
553
+ raise RangeError, "count for element '#{key}' cannot be made negative" if resulting_count < 0
537
554
 
538
- raise RangeError, "count for element '#{key}' cannot be made negative" if resulting_count < 0
555
+ if 0 == resulting_count
539
556
 
540
- if 0 == resulting_count
557
+ @elements.delete key
558
+ else
541
559
 
542
- @elements.delete key
543
- else
560
+ @elements[key] = resulting_count
561
+ end
562
+ @count += count
544
563
 
545
- @elements[key] = resulting_count
564
+ self
546
565
  end
547
- @count += count
548
-
549
- self
550
- end
551
-
552
- # Removes a key-value pair from the instance and return as a two-item
553
- # array
554
- def shift
555
566
 
556
- r = @elements.shift
567
+ # Removes a key-value pair from the instance and return as a two-item
568
+ # array
569
+ def shift
557
570
 
558
- @count -= r[1] if ::Array === r
571
+ r = @elements.shift
559
572
 
560
- r
561
- end
573
+ @count -= r[1] if ::Array === r
562
574
 
563
- alias size length
575
+ r
576
+ end
564
577
 
565
- # Causes an element with the given +key+ and +count+ to be stored. If an
566
- # element with the given +key+ already exists, its count will be adjusted,
567
- # as will the total count
568
- #
569
- # === Return
570
- # +true+ if the element was inserted; +false+ if the element was
571
- # overwritten
572
- def store key, count
578
+ alias size length
573
579
 
574
- raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
580
+ # Causes an element with the given +key+ and +count+ to be stored. If an
581
+ # element with the given +key+ already exists, its count will be adjusted,
582
+ # as will the total count
583
+ #
584
+ # === Return
585
+ # +true+ if the element was inserted; +false+ if the element was
586
+ # overwritten
587
+ def store key, count
575
588
 
576
- old_count = @elements[key] || 0
589
+ raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
577
590
 
578
- @elements.store key, count
591
+ old_count = @elements[key] || 0
579
592
 
580
- @count += count - old_count
593
+ @elements.store key, count
581
594
 
582
- old_count == 0
583
- end
595
+ @count += count - old_count
584
596
 
585
- # Converts instance to an array of +[key,value]+ pairs
586
- def to_a
597
+ old_count == 0
598
+ end
587
599
 
588
- @elements.to_a
589
- end
600
+ # Converts instance to an array of +[key,value]+ pairs
601
+ def to_a
590
602
 
591
- # Obtains reference to internal hash instance (which must *not* be modified)
592
- def to_h
603
+ @elements.to_a
604
+ end
593
605
 
594
- @elements.to_h
595
- end
606
+ # Obtains reference to internal hash instance (which must *not* be modified)
607
+ def to_h
596
608
 
597
- # Obtains equivalent hash to instance
598
- def to_hash
609
+ @elements.to_h
610
+ end
599
611
 
600
- @elements.to_hash
601
- end
612
+ # Obtains equivalent hash to instance
613
+ def to_hash
602
614
 
603
- # A string-form of the instance
604
- def to_s
615
+ @elements.to_hash
616
+ end
605
617
 
606
- @elements.to_s
607
- end
618
+ # A string-form of the instance
619
+ def to_s
608
620
 
609
- # An array of all frequencies (without element keys) in the instance
610
- def values
621
+ @elements.to_s
622
+ end
611
623
 
612
- @elements.values
613
- end
614
- end # class FrequencyMap
624
+ # An array of all frequencies (without element keys) in the instance
625
+ def values
615
626
 
627
+ @elements.values
628
+ end
629
+ end # class FrequencyMap
616
630
  end # module Containers
617
631
  end # module Xqsr3
618
632