xqsr3 0.38.1.1 → 0.39.1

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