Class: Xqsr3::Containers::FrequencyMap

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/xqsr3/containers/frequency_map.rb

Constant Summary collapse

ByElement =
Class.new do

	def self.[] *args

		fm = FrequencyMap.new

		args.each { |el| fm << el }

		fm
	end

	private_class_method :new
end

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#collect_with_index, #unique

Constructor Details

#initializeFrequencyMap

Returns a new instance of FrequencyMap.



134
135
136
137
138
# File 'lib/xqsr3/containers/frequency_map.rb', line 134

def initialize

	@counts	=   {}
	@count	=	0
end

Class Method Details

.[](*args) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/xqsr3/containers/frequency_map.rb', line 71

def self.[] *args

	return self.new if 0 == args.length

	if 1 == args.length

		arg = args[0]

		case	arg
		when	::NilClass

			return self.new
		when	::Hash

			fm = self.new
			arg.each do |k, v|

				fm.store k, v
			end
			return fm
		when	::Array

			# accepted forms:
			#
			# 1. Empty array
			# 2. Array exclusively of two-element arrays
			# 3. Array of even number of elements and at every odd index is an integer

			# 1. Empty array

			return self.new if arg.empty?

			# 2. Array exclusively of two-element arrays

			if arg.all? { |el| ::Array === el && 2 == el.size }

				return self.[](::Hash.[]([ *arg ]))
			end

			# 3. Array of even number of elements and at every odd index is an integer

			if (0 == (arg.size % 2)) && arg.each_with_index.select { |el, index| 1 == (index % 2) }.map(&:first).all? { |el| el.kind_of? ::Integer }

				return self.[](::Hash.[](*arg))
			end


			raise ArgumentError, "array parameter not in an accepted form for subscript initialisation"
		else

			return self.[] arg.to_hash if arg.respond_to? :to_hash

			raise TypeError, "given argument is neither a #{::Hash} nor an #{::Array} and does not respond to the to_hash method"
		end

	else

		# treat all other argument permutations as having passed in an array

		return self.[] [ *args ]
	end
end

Instance Method Details

#<<(key) ⇒ Object



140
141
142
143
# File 'lib/xqsr3/containers/frequency_map.rb', line 140

def << key

	push key, 1
end

#==(rhs) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/xqsr3/containers/frequency_map.rb', line 145

def == rhs

	case	rhs
	when	::NilClass
		return false
	when	::Hash
		return rhs.size == @counts.size && rhs == @counts
	when	self.class
		return rhs.count == self.count && rhs == @counts
	else
		raise TypeError, "can compare #{self.class} only to instances of #{self.class} and #{::Hash}, but #{rhs.class} given"
	end

	false
end

#[](key) ⇒ Object



161
162
163
164
# File 'lib/xqsr3/containers/frequency_map.rb', line 161

def [] key

	@counts[key]
end

#[]=(key, count) ⇒ Object



166
167
168
169
# File 'lib/xqsr3/containers/frequency_map.rb', line 166

def []= key, count

	store key, count
end

#assoc(key) ⇒ Object



171
172
173
174
# File 'lib/xqsr3/containers/frequency_map.rb', line 171

def assoc key

	@counts.assoc key
end

#clearObject



176
177
178
179
180
# File 'lib/xqsr3/containers/frequency_map.rb', line 176

def clear

	@counts.clear
	@count = 0
end

#countObject

The total number of instances recorded



183
184
185
186
# File 'lib/xqsr3/containers/frequency_map.rb', line 183

def count

	@count
end

#defaultObject



188
189
190
191
# File 'lib/xqsr3/containers/frequency_map.rb', line 188

def default

	@counts.default
end

#delete(key) ⇒ Object



193
194
195
196
197
198
# File 'lib/xqsr3/containers/frequency_map.rb', line 193

def delete key

	key_count = @counts.delete key

	@count -= key_count if key_count
end

#dupObject



200
201
202
203
204
205
# File 'lib/xqsr3/containers/frequency_map.rb', line 200

def dup

	fm = self.class.new

	fm.merge! self
end

#eachObject Also known as: each_pair



207
208
209
210
211
212
213
# File 'lib/xqsr3/containers/frequency_map.rb', line 207

def each

	@counts.each do |k, v|

		yield k, v
	end
end

#each_by_frequencyObject

Enumerates each entry pair - element + frequency - in descending order of frequency

Note: this method is expensive, as it must create a new dictionary and map all entries into it in order to achieve the ordering



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/xqsr3/containers/frequency_map.rb', line 220

def each_by_frequency

	tm = {}
	@counts.each do |element, frequency|

		if not tm.has_key? frequency

			tm[frequency] = [element]
		else

			tm[frequency].push element
		end
	end

	keys = tm.keys.sort.reverse
	keys.each do |frequency|

		elements = tm[frequency].sort
		elements.each do |element|

			yield element, frequency
		end
	end
end

#each_keyObject



245
246
247
248
249
250
251
# File 'lib/xqsr3/containers/frequency_map.rb', line 245

def each_key

	keys.each do |element|

		yield element
	end
end

#each_valueObject



255
256
257
258
259
260
261
# File 'lib/xqsr3/containers/frequency_map.rb', line 255

def each_value

	keys.each do |element|

		yield @counts[element]
	end
end

#empty?Boolean

Returns:

  • (Boolean)


263
264
265
266
# File 'lib/xqsr3/containers/frequency_map.rb', line 263

def empty?

	0 == size
end

#eql?(rhs) ⇒ Boolean

Returns:

  • (Boolean)


268
269
270
271
272
273
274
275
276
# File 'lib/xqsr3/containers/frequency_map.rb', line 268

def eql? rhs

	case	rhs
	when	self.class
		return self == rhs
	else
		return false
	end
end

#fetch(key, default = nil, &block) ⇒ Object



278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/xqsr3/containers/frequency_map.rb', line 278

def fetch key, default = nil, &block

	case	default
	when	::NilClass, ::Integer
		;
	else
		raise TypeError, "default parameter ('#{default}') must be of type #{::Integer}, but was of type #{default.class}"
	end

	unless @counts.has_key? key

		return default unless default.nil?

		if block_given?

			case	block.arity
			when	0
				return yield
			when	1
				return yield key
			else
				raise ArgumentError, "given block must take a single parameter - #{block.arity} given"
			end
		end

		raise KeyError, "given key '#{key}' (#{key.class}) does not exist"
	end

	@counts[key]
end

#flattenObject



309
310
311
312
# File 'lib/xqsr3/containers/frequency_map.rb', line 309

def flatten

	@counts.flatten
end

#has_key?(key) ⇒ Boolean Also known as: include?, key?, member?

Returns:

  • (Boolean)


314
315
316
317
# File 'lib/xqsr3/containers/frequency_map.rb', line 314

def has_key? key

	@counts.has_key? key
end

#has_value?(value) ⇒ Boolean

Returns:

  • (Boolean)


319
320
321
322
323
324
325
326
327
328
329
# File 'lib/xqsr3/containers/frequency_map.rb', line 319

def has_value? value

	case	value
	when	::NilClass, ::Integer
		;
	else
		raise TypeError, "parameter ('#{value}') must be of type #{::Integer}, but was of type #{value.class}"
	end

	@counts.has_value? value
end

#hashObject



331
332
333
334
# File 'lib/xqsr3/containers/frequency_map.rb', line 331

def hash

	@counts.hash
end

#inspectObject Also known as: to_s



338
339
340
341
# File 'lib/xqsr3/containers/frequency_map.rb', line 338

def inspect

	@counts.inspect
end

#key(value) ⇒ Object

def keep_if

@counts.keep_if end



348
349
350
351
352
353
354
355
356
357
358
# File 'lib/xqsr3/containers/frequency_map.rb', line 348

def key value

	case	value
	when	::NilClass, ::Integer
		;
	else
		raise TypeError, "parameter ('#{value}') must be of type #{::Integer}, but was of type #{value.class}"
	end

	@counts.key value
end

#keysObject



362
363
364
365
# File 'lib/xqsr3/containers/frequency_map.rb', line 362

def keys

	@counts.keys
end

#lengthObject Also known as: size



367
368
369
370
# File 'lib/xqsr3/containers/frequency_map.rb', line 367

def length

	@counts.length
end

#merge(fm) ⇒ Object

Raises:

  • (TypeError)


374
375
376
377
378
379
380
381
382
383
384
# File 'lib/xqsr3/containers/frequency_map.rb', line 374

def merge fm

	raise TypeError, "parameter must be an instance of type #{self.class}" unless fm.instance_of? self.class

	fm_new = self.class.new

	fm_new.merge! self
	fm_new.merge! fm

	fm_new
end

#merge!(fm) ⇒ Object



386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'lib/xqsr3/containers/frequency_map.rb', line 386

def merge! fm

	fm.each do |k, v|

		if not @counts.has_key? k

			@counts[k]	=	v
		else

			@counts[k]	+=	v
		end
		@count += v
	end

	self
end

#push(element, count = 1) ⇒ Object

Raises:

  • (TypeError)


403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
# File 'lib/xqsr3/containers/frequency_map.rb', line 403

def push element, count = 1

	raise TypeError, "count ('#{count}') must in an instance of #{::Integer}, but #{count.class} provided" unless count.kind_of? ::Integer

	if not @counts.has_key? element

		@counts[element]	=	count
	else

		@counts[element]	+=	count
	end
	@count += count

	self
end

#shiftObject



419
420
421
422
423
424
425
426
# File 'lib/xqsr3/containers/frequency_map.rb', line 419

def shift

	r = @counts.shift

	@count -= r[1] if ::Array === r

	r
end

#store(key, value) ⇒ Object



430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
# File 'lib/xqsr3/containers/frequency_map.rb', line 430

def store key, value

	case	value
	when	::NilClass, ::Integer
		;
	else
		raise TypeError, "value ('#{value}') must be of type #{::Integer}, but was of type #{value.class}"
	end

	key_count = @counts[key] || 0

	@counts.store key, value

	@count += value - key_count
end

#to_aObject



446
447
448
449
# File 'lib/xqsr3/containers/frequency_map.rb', line 446

def to_a

	@counts.to_a
end

#to_hObject



451
452
453
454
# File 'lib/xqsr3/containers/frequency_map.rb', line 451

def to_h

	@counts.to_h
end

#to_hashObject



456
457
458
459
# File 'lib/xqsr3/containers/frequency_map.rb', line 456

def to_hash

	@counts.to_hash
end

#valuesObject



463
464
465
466
# File 'lib/xqsr3/containers/frequency_map.rb', line 463

def values

	@counts.values
end