xqsr3 0.38.2 → 0.39.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -6
  3. data/examples/count_word_frequencies.md +12 -12
  4. data/examples/count_word_frequencies.rb +4 -4
  5. data/lib/xqsr3/array_utilities/join_with_or.rb +47 -47
  6. data/lib/xqsr3/array_utilities.rb +2 -2
  7. data/lib/xqsr3/command_line_utilities/map_option_string.rb +60 -60
  8. data/lib/xqsr3/command_line_utilities.rb +2 -2
  9. data/lib/xqsr3/containers/frequency_map.rb +399 -399
  10. data/lib/xqsr3/containers/multi_map.rb +448 -448
  11. data/lib/xqsr3/containers.rb +3 -3
  12. data/lib/xqsr3/conversion/bool_parser.rb +51 -51
  13. data/lib/xqsr3/conversion/integer_parser.rb +87 -87
  14. data/lib/xqsr3/conversion.rb +3 -3
  15. data/lib/xqsr3/diagnostics/exception_utilities.rb +145 -145
  16. data/lib/xqsr3/diagnostics/exceptions/with_cause.rb +90 -90
  17. data/lib/xqsr3/diagnostics/inspect_builder.rb +80 -80
  18. data/lib/xqsr3/diagnostics.rb +3 -3
  19. data/lib/xqsr3/doc_.rb +130 -130
  20. data/lib/xqsr3/extensions/array/join_with_or.rb +9 -9
  21. data/lib/xqsr3/extensions/enumerable/collect_with_index.rb +12 -12
  22. data/lib/xqsr3/extensions/enumerable/detect_map.rb +35 -35
  23. data/lib/xqsr3/extensions/enumerable/unique.rb +29 -28
  24. data/lib/xqsr3/extensions/hash/deep_transform.rb +1 -1
  25. data/lib/xqsr3/extensions/hash/except.rb +16 -16
  26. data/lib/xqsr3/extensions/hash/has_match.rb +10 -10
  27. data/lib/xqsr3/extensions/hash/match.rb +10 -10
  28. data/lib/xqsr3/extensions/hash/slice.rb +11 -11
  29. data/lib/xqsr3/extensions/hash.rb +1 -1
  30. data/lib/xqsr3/extensions/integer/to_s_grp.rb +118 -0
  31. data/lib/xqsr3/extensions/integer.rb +3 -0
  32. data/lib/xqsr3/extensions/io/writelines.rb +28 -28
  33. data/lib/xqsr3/extensions/kernel/integer.rb +20 -20
  34. data/lib/xqsr3/extensions/kernel/raise_with_options.rb +8 -8
  35. data/lib/xqsr3/extensions/kernel.rb +1 -0
  36. data/lib/xqsr3/extensions/string/ends_with.rb +1 -1
  37. data/lib/xqsr3/extensions/string/map_option_string.rb +4 -4
  38. data/lib/xqsr3/extensions/string/nil_if_empty.rb +1 -1
  39. data/lib/xqsr3/extensions/string/nil_if_whitespace.rb +1 -1
  40. data/lib/xqsr3/extensions/string/quote_if.rb +1 -1
  41. data/lib/xqsr3/extensions/string/starts_with.rb +1 -1
  42. data/lib/xqsr3/extensions/string/to_bool.rb +8 -8
  43. data/lib/xqsr3/extensions/string/to_symbol.rb +1 -1
  44. data/lib/xqsr3/extensions/string/truncate.rb +1 -1
  45. data/lib/xqsr3/extensions/test/unit/assert_eql.rb +7 -7
  46. data/lib/xqsr3/extensions/test/unit/assert_false.rb +6 -6
  47. data/lib/xqsr3/extensions/test/unit/assert_not.rb +6 -6
  48. data/lib/xqsr3/extensions/test/unit/assert_not_eql.rb +7 -7
  49. data/lib/xqsr3/extensions/test/unit/assert_raise_with_message.rb +61 -61
  50. data/lib/xqsr3/extensions/test/unit/assert_subclass_of.rb +7 -7
  51. data/lib/xqsr3/extensions/test/unit/assert_superclass_of.rb +7 -7
  52. data/lib/xqsr3/extensions/test/unit/assert_true.rb +6 -6
  53. data/lib/xqsr3/extensions/test/unit/assert_type_has_instance_methods.rb +36 -36
  54. data/lib/xqsr3/extensions.rb +5 -5
  55. data/lib/xqsr3/hash_utilities/deep_transform.rb +65 -65
  56. data/lib/xqsr3/hash_utilities/key_matching.rb +77 -77
  57. data/lib/xqsr3/hash_utilities.rb +3 -3
  58. data/lib/xqsr3/internal_/test_unit_version_.rb +85 -85
  59. data/lib/xqsr3/io/writelines.rb +119 -119
  60. data/lib/xqsr3/quality/parameter_checking.rb +445 -445
  61. data/lib/xqsr3/quality.rb +2 -2
  62. data/lib/xqsr3/string_utilities/ends_with.rb +59 -59
  63. data/lib/xqsr3/string_utilities/nil_if_empty.rb +28 -28
  64. data/lib/xqsr3/string_utilities/nil_if_whitespace.rb +29 -29
  65. data/lib/xqsr3/string_utilities/quote_if.rb +50 -50
  66. data/lib/xqsr3/string_utilities/starts_with.rb +59 -59
  67. data/lib/xqsr3/string_utilities/to_symbol.rb +75 -75
  68. data/lib/xqsr3/string_utilities/truncate.rb +55 -55
  69. data/lib/xqsr3/string_utilities.rb +8 -8
  70. data/lib/xqsr3/version.rb +12 -12
  71. data/test/performance/frequency_map.rb +12 -12
  72. data/test/scratch/test_assert_raise_with_message.rb +11 -11
  73. data/test/unit/array_utilities/tc_join_with_or.rb +140 -140
  74. data/test/unit/command_line_utilities/tc_map_option_string.rb +18 -18
  75. data/test/unit/containers/tc_frequency_map.rb +591 -591
  76. data/test/unit/containers/tc_multi_map.rb +558 -558
  77. data/test/unit/conversion/tc_integer_parser.rb +72 -72
  78. data/test/unit/conversion/tc_to_bool.rb +25 -25
  79. data/test/unit/diagnostics/exceptions/tc_with_cause.rb +165 -165
  80. data/test/unit/diagnostics/tc_exception_utilities.rb +156 -156
  81. data/test/unit/extensions/enumerable/tc_collect_with_index.rb +14 -14
  82. data/test/unit/extensions/enumerable/tc_detect_map.rb +20 -20
  83. data/test/unit/extensions/enumerable/tc_unique.rb +34 -34
  84. data/test/unit/extensions/hash/tc_deep_transform.rb +22 -22
  85. data/test/unit/extensions/hash/tc_except.rb +28 -28
  86. data/test/unit/extensions/hash/tc_slice.rb +13 -13
  87. data/test/unit/extensions/integer/tc_to_s_grp.rb +60 -0
  88. data/test/unit/extensions/integer/ts_all.rb +12 -0
  89. data/test/unit/extensions/io/tc_writelines.rb +77 -77
  90. data/test/unit/extensions/kernel/tc_integer.rb +75 -75
  91. data/test/unit/extensions/kernel/tc_raise_with_options.rb +155 -155
  92. data/test/unit/extensions/object/tc_inspect.rb +50 -50
  93. data/test/unit/extensions/string/tc_bool.tb +24 -24
  94. data/test/unit/extensions/string/tc_ends_with.rb +53 -53
  95. data/test/unit/extensions/string/tc_map_option_string.rb +15 -15
  96. data/test/unit/extensions/string/tc_nil_if_empty.rb +8 -8
  97. data/test/unit/extensions/string/tc_nil_if_whitespace.rb +8 -8
  98. data/test/unit/extensions/string/tc_quote_if.rb +18 -18
  99. data/test/unit/extensions/string/tc_starts_with.rb +53 -53
  100. data/test/unit/extensions/string/tc_to_symbol.rb +26 -26
  101. data/test/unit/extensions/string/tc_truncate.rb +18 -18
  102. data/test/unit/extensions/test/unit/tc_assert_raise_with_message.rb +16 -16
  103. data/test/unit/extensions/test/unit/tc_assert_subclass_of.rb +9 -9
  104. data/test/unit/extensions/test/unit/tc_assert_superclass_of.rb +9 -9
  105. data/test/unit/hash_utilities/tc_has_match.rb +70 -70
  106. data/test/unit/hash_utilities/tc_match.rb +83 -83
  107. data/test/unit/io/tc_writelines.rb +106 -106
  108. data/test/unit/quality/tc_parameter_checking.rb +389 -389
  109. data/test/unit/string_utilities/tc_truncate.rb +27 -27
  110. data/test/unit/tc_version.rb +15 -15
  111. metadata +6 -2
@@ -5,13 +5,13 @@
5
5
  # Purpose: FrequencyMap container
6
6
  #
7
7
  # Created: 28th January 2005
8
- # Updated: 11th December 2023
8
+ # Updated: 29th March 2024
9
9
  #
10
10
  # Home: http://github.com/synesissoftware/xqsr3
11
11
  #
12
12
  # Author: Matthew Wilson
13
13
  #
14
- # Copyright (c) 2019-2023, Matthew Wilson and Synesis Information Systems
14
+ # Copyright (c) 2019-2024, Matthew Wilson and Synesis Information Systems
15
15
  # Copyright (c) 2005-2019, Matthew Wilson and Synesis Software
16
16
  # All rights reserved.
17
17
  #
@@ -57,560 +57,560 @@ module Containers
57
57
  # elements, as the map's keys
58
58
  class FrequencyMap
59
59
 
60
- include Enumerable
61
- include ::Xqsr3::Diagnostics::InspectBuilder
60
+ include Enumerable
61
+ include ::Xqsr3::Diagnostics::InspectBuilder
62
62
 
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
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
80
 
81
- # Create an instance of Xqsr3::FrequencyMap from an array
82
- def self.[] *args
81
+ # Create an instance of Xqsr3::FrequencyMap from an array
82
+ def self.[] *args
83
83
 
84
- fm = FrequencyMap.new
84
+ fm = FrequencyMap.new
85
85
 
86
- args.each { |el| fm << el }
86
+ args.each { |el| fm << el }
87
87
 
88
- fm
89
- end
88
+ fm
89
+ end
90
90
 
91
- private_class_method :new
92
- end
91
+ private_class_method :new
92
+ end
93
93
 
94
- # Creates an instance from the given arguments
95
- def self.[] *args
94
+ # Creates an instance from the given arguments
95
+ def self.[] *args
96
96
 
97
- return self.new if 0 == args.length
97
+ return self.new if 0 == args.length
98
98
 
99
- if 1 == args.length
99
+ if 1 == args.length
100
100
 
101
- arg = args[0]
101
+ arg = args[0]
102
102
 
103
- case arg
104
- when ::NilClass
103
+ case arg
104
+ when ::NilClass
105
105
 
106
- return self.new
107
- when ::Hash
106
+ return self.new
107
+ when ::Hash
108
108
 
109
- fm = self.new
110
- arg.each do |k, v|
109
+ fm = self.new
110
+ arg.each do |k, v|
111
111
 
112
- fm.store k, v
113
- end
114
- return fm
115
- when ::Array
112
+ fm.store k, v
113
+ end
114
+ return fm
115
+ when ::Array
116
116
 
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
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
122
122
 
123
- # 1. Empty array
123
+ # 1. Empty array
124
124
 
125
- return self.new if arg.empty?
125
+ return self.new if arg.empty?
126
126
 
127
- # 2. Array exclusively of two-element arrays
127
+ # 2. Array exclusively of two-element arrays
128
128
 
129
- if arg.all? { |el| ::Array === el && 2 == el.size }
129
+ if arg.all? { |el| ::Array === el && 2 == el.size }
130
130
 
131
- return self.[](::Hash.[]([ *arg ]))
132
- end
131
+ return self.[](::Hash.[]([ *arg ]))
132
+ end
133
133
 
134
- # 3. Array of even number of elements and at every odd index is an integer
134
+ # 3. Array of even number of elements and at every odd index is an integer
135
135
 
136
- if (0 == (arg.size % 2)) && arg.each_with_index.select { |el, index| 1 == (index % 2) }.map(&:first).all? { |el| el.kind_of? ::Integer }
136
+ if (0 == (arg.size % 2)) && arg.each_with_index.select { |el, index| 1 == (index % 2) }.map(&:first).all? { |el| el.kind_of? ::Integer }
137
137
 
138
- return self.[](::Hash.[](*arg))
139
- end
138
+ return self.[](::Hash.[](*arg))
139
+ end
140
140
 
141
141
 
142
- raise ArgumentError, "array parameter not in an accepted form for subscript initialisation"
143
- else
142
+ raise ArgumentError, "array parameter not in an accepted form for subscript initialisation"
143
+ else
144
144
 
145
- return self.[] arg.to_hash if arg.respond_to? :to_hash
145
+ return self.[] arg.to_hash if arg.respond_to? :to_hash
146
146
 
147
- raise TypeError, "given argument is neither a #{::Hash} nor an #{::Array} and does not respond to the to_hash method"
148
- end
147
+ raise TypeError, "given argument is neither a #{::Hash} nor an #{::Array} and does not respond to the to_hash method"
148
+ end
149
149
 
150
- else
150
+ else
151
151
 
152
- # treat all other argument permutations as having passed in an array
152
+ # treat all other argument permutations as having passed in an array
153
153
 
154
- return self.[] [ *args ]
155
- end
156
- end
154
+ return self.[] [ *args ]
155
+ end
156
+ end
157
157
 
158
- # Initialises an instance
159
- def initialize
158
+ # Initialises an instance
159
+ def initialize
160
160
 
161
- @elements = {}
162
- @count = 0
163
- end
161
+ @elements = {}
162
+ @count = 0
163
+ end
164
164
 
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
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
170
170
 
171
- push key, 1
172
- end
171
+ push key, 1
172
+ end
173
173
 
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
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
182
182
 
183
- case rhs
184
- when ::NilClass
183
+ case rhs
184
+ when ::NilClass
185
185
 
186
- return false
187
- when ::Hash
186
+ return false
187
+ when ::Hash
188
188
 
189
- return rhs.size == @elements.size && rhs == @elements
190
- when self.class
189
+ return rhs.size == @elements.size && rhs == @elements
190
+ when self.class
191
191
 
192
- return rhs.count == self.count && rhs == @elements
193
- else
192
+ return rhs.count == self.count && rhs == @elements
193
+ else
194
194
 
195
- raise TypeError, "can compare #{self.class} only to instances of #{self.class} and #{::Hash}, but #{rhs.class} given"
196
- end
195
+ raise TypeError, "can compare #{self.class} only to instances of #{self.class} and #{::Hash}, but #{rhs.class} given"
196
+ end
197
197
 
198
- false
199
- end
198
+ false
199
+ end
200
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
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
206
 
207
- @elements[key] || 0
208
- end
207
+ @elements[key] || 0
208
+ end
209
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
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
219
219
 
220
- raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
220
+ raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
221
221
 
222
- store key, count
223
- end
222
+ store key, count
223
+ end
224
224
 
225
- # Searches the instance comparing each element with +key+, returning the
226
- # count if found, or +nil+ if not
227
- def assoc key
225
+ # Searches the instance comparing each element with +key+, returning the
226
+ # count if found, or +nil+ if not
227
+ def assoc key
228
228
 
229
- @elements.assoc key
230
- end
229
+ @elements.assoc key
230
+ end
231
231
 
232
- # Removes all elements from the instance
233
- def clear
232
+ # Removes all elements from the instance
233
+ def clear
234
234
 
235
- @elements.clear
236
- @count = 0
237
- end
235
+ @elements.clear
236
+ @count = 0
237
+ end
238
238
 
239
- # The total number of instances recorded
240
- def count
239
+ # The total number of instances recorded
240
+ def count
241
241
 
242
- @count
243
- end
242
+ @count
243
+ end
244
244
 
245
- # Obtains the default value of the instance, which will always be +nil+
246
- def default
245
+ # Obtains the default value of the instance, which will always be +nil+
246
+ def default
247
247
 
248
- @elements.default
249
- end
248
+ @elements.default
249
+ end
250
250
 
251
- # Deletes the element with the given +key+ and its counts
252
- #
253
- # * *Parameters:*
254
- # - +key+ The key to delete
255
- def delete key
251
+ # Deletes the element with the given +key+ and its counts
252
+ #
253
+ # * *Parameters:*
254
+ # - +key+ The key to delete
255
+ def delete key
256
256
 
257
- key_count = @elements.delete key
257
+ key_count = @elements.delete key
258
258
 
259
- @count -= key_count if key_count
260
- end
259
+ @count -= key_count if key_count
260
+ end
261
261
 
262
- # Duplicates the instance
263
- def dup
262
+ # Duplicates the instance
263
+ def dup
264
264
 
265
- fm = self.class.new
265
+ fm = self.class.new
266
266
 
267
- fm.merge! self
268
- end
267
+ fm.merge! self
268
+ end
269
269
 
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
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
274
274
 
275
- return @elements.each unless block_given?
275
+ return @elements.each unless block_given?
276
276
 
277
- @elements.each do |k, v|
277
+ @elements.each do |k, v|
278
278
 
279
- yield k, v
280
- end
281
- end
279
+ yield k, v
280
+ end
281
+ end
282
282
 
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
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
288
288
 
289
- sorted_elements = @elements.sort { |a, b| a[0] <=> b[0] }
289
+ sorted_elements = @elements.sort { |a, b| a[0] <=> b[0] }
290
290
 
291
- return sorted_elements.each unless block_given?
291
+ return sorted_elements.each unless block_given?
292
292
 
293
- sorted_elements.each do |k, v|
293
+ sorted_elements.each do |k, v|
294
294
 
295
- yield k, v
296
- end
297
- end
295
+ yield k, v
296
+ end
297
+ end
298
298
 
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
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
305
305
 
306
- ar = @elements.to_a.sort { |a, b| b[1] <=> a[1] }
306
+ ar = @elements.to_a.sort { |a, b| b[1] <=> a[1] }
307
307
 
308
- return ar.each unless block_given?
308
+ return ar.each unless block_given?
309
309
 
310
- ar.each do |k, v|
310
+ ar.each do |k, v|
311
311
 
312
- yield k, v
313
- end
314
- end
312
+ yield k, v
313
+ end
314
+ end
315
315
 
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
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
319
319
 
320
- return @elements.each_key unless block_given?
320
+ return @elements.each_key unless block_given?
321
321
 
322
- keys.each do |element|
322
+ keys.each do |element|
323
323
 
324
- yield element
325
- end
326
- end
324
+ yield element
325
+ end
326
+ end
327
327
 
328
- alias each_pair each
328
+ alias each_pair each
329
329
 
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
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
333
333
 
334
- return @elements.each_value unless block_given?
334
+ return @elements.each_value unless block_given?
335
335
 
336
- keys.each do |element|
336
+ keys.each do |element|
337
337
 
338
- yield @elements[element]
339
- end
340
- end
338
+ yield @elements[element]
339
+ end
340
+ end
341
341
 
342
- # Returns +true+ if instance contains no elements; +false+ otherwise
343
- def empty?
342
+ # Returns +true+ if instance contains no elements; +false+ otherwise
343
+ def empty?
344
344
 
345
- 0 == size
346
- end
345
+ 0 == size
346
+ end
347
347
 
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
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
351
351
 
352
- case rhs
353
- when self.class
354
- return self == rhs
355
- else
356
- return false
357
- end
358
- end
352
+ case rhs
353
+ when self.class
354
+ return self == rhs
355
+ else
356
+ return false
357
+ end
358
+ end
359
359
 
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
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
366
366
 
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
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
373
373
 
374
- unless @elements.has_key? key
374
+ unless @elements.has_key? key
375
375
 
376
- return default unless default.nil?
376
+ return default unless default.nil?
377
377
 
378
- if block_given?
378
+ if block_given?
379
379
 
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"
387
- end
388
- end
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"
387
+ end
388
+ end
389
389
 
390
- raise KeyError, "given key '#{key}' (#{key.class}) does not exist"
391
- end
390
+ raise KeyError, "given key '#{key}' (#{key.class}) does not exist"
391
+ end
392
392
 
393
- @elements[key]
394
- end
393
+ @elements[key]
394
+ end
395
395
 
396
- # Returns the equivalent flattened form of the instance
397
- def flatten
396
+ # Returns the equivalent flattened form of the instance
397
+ def flatten
398
398
 
399
- @elements.flatten
400
- end
399
+ @elements.flatten
400
+ end
401
401
 
402
- # Returns +true+ if an element with the given +key+ is in the map; +false+
403
- # otherwise
404
- def has_key? key
402
+ # Returns +true+ if an element with the given +key+ is in the map; +false+
403
+ # otherwise
404
+ def has_key? key
405
405
 
406
- @elements.has_key? key
407
- end
406
+ @elements.has_key? key
407
+ end
408
408
 
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
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
418
418
 
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}"
424
- end
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}"
424
+ end
425
425
 
426
- @elements.has_value? value
427
- end
426
+ @elements.has_value? value
427
+ end
428
428
 
429
- # A hash-code for this instance
430
- def hash
429
+ # A hash-code for this instance
430
+ def hash
431
431
 
432
- @elements.hash
433
- end
432
+ @elements.hash
433
+ end
434
434
 
435
- alias include? has_key?
436
-
437
- # A diagnostics string form of the instance
438
- def inspect
439
-
440
- make_inspect show_fields: true
441
- end
442
-
443
- # def keep_if
435
+ alias include? has_key?
436
+
437
+ # A diagnostics string form of the instance
438
+ def inspect
439
+
440
+ make_inspect show_fields: true
441
+ end
442
+
443
+ # def keep_if
444
444
  #
445
- # @elements.keep_if
446
- # end
445
+ # @elements.keep_if
446
+ # end
447
447
  =begin
448
448
  =end
449
449
 
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
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
458
458
 
459
- raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
459
+ raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
460
460
 
461
- @elements.key count
462
- end
461
+ @elements.key count
462
+ end
463
463
 
464
- alias key? has_key?
464
+ alias key? has_key?
465
465
 
466
- # An array of the elements only
467
- def keys
466
+ # An array of the elements only
467
+ def keys
468
468
 
469
- @elements.keys
470
- end
469
+ @elements.keys
470
+ end
471
471
 
472
- # The number of elements in the map
473
- def length
472
+ # The number of elements in the map
473
+ def length
474
474
 
475
- @elements.length
476
- end
475
+ @elements.length
476
+ end
477
477
 
478
- alias member? has_key?
478
+ alias member? has_key?
479
479
 
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
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
486
486
 
487
- raise TypeError, "parameter must be an instance of type #{self.class}" unless fm.instance_of? self.class
487
+ raise TypeError, "parameter must be an instance of type #{self.class}" unless fm.instance_of? self.class
488
488
 
489
- fm_new = self.class.new
489
+ fm_new = self.class.new
490
490
 
491
- fm_new.merge! self
492
- fm_new.merge! fm
491
+ fm_new.merge! self
492
+ fm_new.merge! fm
493
493
 
494
- fm_new
495
- end
494
+ fm_new
495
+ end
496
496
 
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
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
502
502
 
503
- fm.each do |k, v|
503
+ fm.each do |k, v|
504
504
 
505
- if not @elements.has_key? k
505
+ if not @elements.has_key? k
506
506
 
507
- @elements[k] = v
508
- else
507
+ @elements[k] = v
508
+ else
509
509
 
510
- @elements[k] += v
511
- end
512
- @count += v
513
- end
510
+ @elements[k] += v
511
+ end
512
+ @count += v
513
+ end
514
514
 
515
- self
516
- end
515
+ self
516
+ end
517
517
 
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
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
532
532
 
533
- raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
533
+ raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
534
534
 
535
- initial_count = @elements[key] || 0
536
- resulting_count = initial_count + count
535
+ initial_count = @elements[key] || 0
536
+ resulting_count = initial_count + count
537
537
 
538
- raise RangeError, "count for element '#{key}' cannot be made negative" if resulting_count < 0
538
+ raise RangeError, "count for element '#{key}' cannot be made negative" if resulting_count < 0
539
539
 
540
- if 0 == resulting_count
540
+ if 0 == resulting_count
541
541
 
542
- @elements.delete key
543
- else
542
+ @elements.delete key
543
+ else
544
544
 
545
- @elements[key] = resulting_count
546
- end
547
- @count += count
545
+ @elements[key] = resulting_count
546
+ end
547
+ @count += count
548
548
 
549
- self
550
- end
549
+ self
550
+ end
551
551
 
552
- # Removes a key-value pair from the instance and return as a two-item
553
- # array
554
- def shift
552
+ # Removes a key-value pair from the instance and return as a two-item
553
+ # array
554
+ def shift
555
555
 
556
- r = @elements.shift
556
+ r = @elements.shift
557
557
 
558
- @count -= r[1] if ::Array === r
558
+ @count -= r[1] if ::Array === r
559
559
 
560
- r
561
- end
560
+ r
561
+ end
562
562
 
563
- alias size length
563
+ alias size length
564
564
 
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
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
573
573
 
574
- raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
574
+ raise TypeError, "'count' parameter must be of type #{::Integer}, but was of type #{count.class}" unless Integer === count
575
575
 
576
- old_count = @elements[key] || 0
576
+ old_count = @elements[key] || 0
577
577
 
578
- @elements.store key, count
578
+ @elements.store key, count
579
579
 
580
- @count += count - old_count
580
+ @count += count - old_count
581
581
 
582
- old_count == 0
583
- end
582
+ old_count == 0
583
+ end
584
584
 
585
- # Converts instance to an array of +[key,value]+ pairs
586
- def to_a
585
+ # Converts instance to an array of +[key,value]+ pairs
586
+ def to_a
587
587
 
588
- @elements.to_a
589
- end
588
+ @elements.to_a
589
+ end
590
590
 
591
- # Obtains reference to internal hash instance (which must *not* be modified)
592
- def to_h
591
+ # Obtains reference to internal hash instance (which must *not* be modified)
592
+ def to_h
593
593
 
594
- @elements.to_h
595
- end
594
+ @elements.to_h
595
+ end
596
596
 
597
- # Obtains equivalent hash to instance
598
- def to_hash
597
+ # Obtains equivalent hash to instance
598
+ def to_hash
599
599
 
600
- @elements.to_hash
601
- end
600
+ @elements.to_hash
601
+ end
602
602
 
603
- # A string-form of the instance
604
- def to_s
603
+ # A string-form of the instance
604
+ def to_s
605
605
 
606
- @elements.to_s
607
- end
606
+ @elements.to_s
607
+ end
608
608
 
609
- # An array of all frequencies (without element keys) in the instance
610
- def values
609
+ # An array of all frequencies (without element keys) in the instance
610
+ def values
611
611
 
612
- @elements.values
613
- end
612
+ @elements.values
613
+ end
614
614
  end # class FrequencyMap
615
615
 
616
616
  end # module Containers