eymiha_util 0.1.6 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/gem_package.rb +3 -3
- data/html/classes/Eymiha.html +144 -0
- data/html/classes/{BaseEnvelope.html → Eymiha/BaseEnvelope.html} +21 -21
- data/html/classes/Eymiha/BaseEnvelope.src/M000010.html +18 -0
- data/html/classes/Eymiha/BaseEnvelope.src/M000011.html +20 -0
- data/html/classes/Eymiha/BaseEnvelope.src/M000012.html +18 -0
- data/html/classes/{Enum.html → Eymiha/Enum.html} +5 -27
- data/html/classes/{Envelope.html → Eymiha/Envelope.html} +52 -52
- data/html/classes/Eymiha/Envelope.src/M000025.html +19 -0
- data/html/classes/Eymiha/Envelope.src/M000026.html +19 -0
- data/html/classes/Eymiha/Envelope.src/M000027.html +35 -0
- data/html/classes/Eymiha/Envelope.src/M000028.html +19 -0
- data/html/classes/Eymiha/Envelope.src/M000029.html +19 -0
- data/html/classes/Eymiha/Envelope.src/M000030.html +26 -0
- data/html/classes/Eymiha/Envelope.src/M000032.html +18 -0
- data/html/classes/{EnvelopeException.html → Eymiha/EnvelopeException.html} +5 -5
- data/html/classes/{ForwardReference.html → Eymiha/ForwardReference.html} +16 -16
- data/html/classes/Eymiha/ForwardReference.src/M000033.html +21 -0
- data/html/classes/Eymiha/ForwardReference.src/M000034.html +18 -0
- data/html/classes/{ForwardReferencer.html → Eymiha/ForwardReferencer.html} +12 -5
- data/html/classes/{ForwardReferencing.html → Eymiha/ForwardReferencing.html} +51 -51
- data/html/classes/Eymiha/ForwardReferencing.src/M000001.html +20 -0
- data/html/classes/Eymiha/ForwardReferencing.src/M000002.html +20 -0
- data/html/classes/Eymiha/ForwardReferencing.src/M000003.html +20 -0
- data/html/classes/Eymiha/ForwardReferencing.src/M000004.html +32 -0
- data/html/classes/Eymiha/ForwardReferencing.src/M000005.html +18 -0
- data/html/classes/Eymiha/ForwardReferencing.src/M000006.html +25 -0
- data/html/classes/Eymiha/ForwardReferencing.src/M000007.html +18 -0
- data/html/classes/Eymiha/ForwardReferencing.src/M000008.html +18 -0
- data/html/classes/Eymiha/ForwardReferencing.src/M000009.html +18 -0
- data/html/classes/{Histogram.html → Eymiha/Histogram.html} +65 -65
- data/html/classes/Eymiha/Histogram.src/M000016.html +19 -0
- data/html/classes/Eymiha/Histogram.src/M000017.html +21 -0
- data/html/classes/Eymiha/Histogram.src/M000018.html +37 -0
- data/html/classes/Eymiha/Histogram.src/M000019.html +18 -0
- data/html/classes/{Histogram.src/M000015.html → Eymiha/Histogram.src/M000020.html} +5 -9
- data/html/classes/Eymiha/Histogram.src/M000021.html +20 -0
- data/html/classes/Eymiha/Histogram.src/M000022.html +20 -0
- data/html/classes/Eymiha/Histogram.src/M000023.html +20 -0
- data/html/classes/Eymiha/Histogram.src/M000024.html +24 -0
- data/html/classes/{HistogramException.html → Eymiha/HistogramException.html} +5 -5
- data/html/classes/{MethodicHash.html → Eymiha/MethodicHash.html} +22 -22
- data/html/classes/Eymiha/MethodicHash.src/M000013.html +22 -0
- data/html/classes/Eymiha/MethodicHash.src/M000014.html +23 -0
- data/html/classes/Eymiha/MethodicHash.src/M000015.html +23 -0
- data/html/created.rid +1 -1
- data/html/files/lib/{enum_rb.html → eymiha/util/enum_rb.html} +3 -3
- data/html/files/lib/{envelope_rb.html → eymiha/util/envelope_rb.html} +3 -3
- data/html/files/lib/{forward_referencing_rb.html → eymiha/util/forward_referencing_rb.html} +6 -8
- data/html/files/lib/{histogram_rb.html → eymiha/util/histogram_rb.html} +3 -3
- data/html/files/lib/eymiha/util/methodic_hash_rb.html +101 -0
- data/html/files/lib/eymiha/util_rb.html +112 -0
- data/html/fr_class_index.html +11 -10
- data/html/fr_file_index.html +6 -5
- data/html/fr_method_index.html +34 -34
- data/html/index.html +1 -1
- data/lib/eymiha/util.rb +5 -0
- data/lib/eymiha/util/enum.rb +59 -0
- data/lib/eymiha/util/envelope.rb +130 -0
- data/lib/eymiha/util/forward_referencing.rb +161 -0
- data/lib/eymiha/util/histogram.rb +112 -0
- data/lib/eymiha/util/methodic_hash.rb +70 -0
- data/test/tc_enum.rb +1 -1
- data/test/tc_envelope.rb +4 -2
- data/test/tc_forward_referencing.rb +3 -1
- data/test/tc_histogram.rb +3 -1
- data/test/tc_methodic_hash.rb +4 -1
- metadata +70 -62
- data/html/classes/BaseEnvelope.src/M000001.html +0 -18
- data/html/classes/BaseEnvelope.src/M000002.html +0 -20
- data/html/classes/BaseEnvelope.src/M000003.html +0 -18
- data/html/classes/Envelope.src/M000016.html +0 -19
- data/html/classes/Envelope.src/M000017.html +0 -19
- data/html/classes/Envelope.src/M000018.html +0 -35
- data/html/classes/Envelope.src/M000019.html +0 -19
- data/html/classes/Envelope.src/M000020.html +0 -19
- data/html/classes/Envelope.src/M000021.html +0 -26
- data/html/classes/Envelope.src/M000023.html +0 -18
- data/html/classes/ForwardReference.src/M000024.html +0 -21
- data/html/classes/ForwardReference.src/M000025.html +0 -18
- data/html/classes/ForwardReferencing.src/M000026.html +0 -20
- data/html/classes/ForwardReferencing.src/M000027.html +0 -20
- data/html/classes/ForwardReferencing.src/M000028.html +0 -20
- data/html/classes/ForwardReferencing.src/M000029.html +0 -32
- data/html/classes/ForwardReferencing.src/M000030.html +0 -18
- data/html/classes/ForwardReferencing.src/M000031.html +0 -25
- data/html/classes/ForwardReferencing.src/M000032.html +0 -18
- data/html/classes/ForwardReferencing.src/M000033.html +0 -18
- data/html/classes/ForwardReferencing.src/M000034.html +0 -18
- data/html/classes/Histogram.src/M000007.html +0 -19
- data/html/classes/Histogram.src/M000008.html +0 -21
- data/html/classes/Histogram.src/M000009.html +0 -37
- data/html/classes/Histogram.src/M000010.html +0 -18
- data/html/classes/Histogram.src/M000011.html +0 -20
- data/html/classes/Histogram.src/M000012.html +0 -20
- data/html/classes/Histogram.src/M000013.html +0 -20
- data/html/classes/Histogram.src/M000014.html +0 -20
- data/html/classes/MethodicHash.src/M000004.html +0 -22
- data/html/classes/MethodicHash.src/M000005.html +0 -23
- data/html/classes/MethodicHash.src/M000006.html +0 -23
- data/html/files/lib/methodic_hash_rb.html +0 -140
- data/lib/enum.rb +0 -57
- data/lib/envelope.rb +0 -126
- data/lib/forward_referencing.rb +0 -157
- data/lib/histogram.rb +0 -109
- data/lib/methodic_hash.rb +0 -66
@@ -0,0 +1,130 @@
|
|
1
|
+
# Envelopes are useful when finding the boundaries of a set of instances.
|
2
|
+
# They expand as new values are added, and keep track of how many items
|
3
|
+
# have been added to construct them.
|
4
|
+
|
5
|
+
module Eymiha
|
6
|
+
|
7
|
+
# An EnvelopeException is generally raised when adding an object to an
|
8
|
+
# instance that it does not know how to interpret, or when requesting
|
9
|
+
# bounderies before any values have been added.
|
10
|
+
class EnvelopeException < Exception
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
# A BaseEnvelope provides a means to keep and provide a count of objects
|
15
|
+
# that have been added to an envelope.
|
16
|
+
class BaseEnvelope
|
17
|
+
|
18
|
+
# Called when requesting envelope bounderies before any values have been
|
19
|
+
# added.
|
20
|
+
def raise_no_envelope
|
21
|
+
raise EnvelopeException, "No values are enveloped"
|
22
|
+
end
|
23
|
+
|
24
|
+
# Called when the value cannot be compared with the the boundaries of the
|
25
|
+
# instance.
|
26
|
+
def raise_no_compare(value=nil)
|
27
|
+
value = "'#{value}' " unless value == nil
|
28
|
+
raise EnvelopeException,
|
29
|
+
"The value #{value}cannot be compared with the envelope"
|
30
|
+
end
|
31
|
+
|
32
|
+
# count of added values reader.
|
33
|
+
attr_reader :count
|
34
|
+
|
35
|
+
# Returns a new instance with no values added.
|
36
|
+
def initialize
|
37
|
+
@count = 0
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
# An Envelope is the minimum envelope that will completely contain a set of
|
44
|
+
# values. Values may be added to an instance, and it can return the number
|
45
|
+
# of values considered so far and its high and low boundaries.
|
46
|
+
#
|
47
|
+
# Envelopes can be used to generate ranges, however the result may be of
|
48
|
+
# limited utility if the types of values being enveloped don't play nicely
|
49
|
+
# with ranges.
|
50
|
+
class Envelope < BaseEnvelope
|
51
|
+
|
52
|
+
# Creates and returns an instance. If an argument is given, it is passed
|
53
|
+
# to the set method to initialize the new instance.
|
54
|
+
def initialize(value=nil)
|
55
|
+
super()
|
56
|
+
add(value) unless value == nil
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns a string representation of the instance.
|
60
|
+
def to_s
|
61
|
+
values = (count > 0)? "\n high #{high}\n low #{low}" : ""
|
62
|
+
"Envelope: count #{count}#{values}"
|
63
|
+
end
|
64
|
+
|
65
|
+
# Adds a value to the instance. When
|
66
|
+
# * x is an Envelope, it is coalesced into the instance.
|
67
|
+
# * otherwise, the envelope is extened to contain the value.
|
68
|
+
# * if the value cannot be compared to the boundaries, an EnvelopeException is raised.
|
69
|
+
# The modified instance is returned.
|
70
|
+
def add(value)
|
71
|
+
if value.kind_of? Envelope
|
72
|
+
count = value.count
|
73
|
+
if (count > 0)
|
74
|
+
add value.high
|
75
|
+
add value.low
|
76
|
+
@count += (count-2)
|
77
|
+
end
|
78
|
+
self
|
79
|
+
else
|
80
|
+
begin
|
81
|
+
@high = value if (@count == 0 || value > @high)
|
82
|
+
@low = value if (@count == 0 || value < @low)
|
83
|
+
@count += 1
|
84
|
+
self
|
85
|
+
rescue
|
86
|
+
raise_no_compare value
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns the high boundary of the instance.
|
92
|
+
# * if there are no boundaries, an EnvelopeException is raised.
|
93
|
+
def high
|
94
|
+
raise_no_envelope if @count == 0
|
95
|
+
@high
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns the low boundary of the instance.
|
99
|
+
# * if there are no boundaries, an EnvelopeException is raised.
|
100
|
+
def low
|
101
|
+
raise_no_envelope if @count == 0
|
102
|
+
@low
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns true if the instance completely contains the argument:
|
106
|
+
# * value is an Envelope, its high and low are contained.
|
107
|
+
# * otherwise, the value is contained.
|
108
|
+
# * if the value cannot be compared to the boundaries, an EnvelopeException is raised.
|
109
|
+
def contains?(value)
|
110
|
+
if value.kind_of? Envelope
|
111
|
+
(contains? value.high) && (contains? value.low)
|
112
|
+
else
|
113
|
+
begin
|
114
|
+
(value >= low) && (value <= high)
|
115
|
+
rescue
|
116
|
+
raise_no_compare value
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
alias === contains?
|
122
|
+
|
123
|
+
# Returns an inclusive range from the low to high boundaries
|
124
|
+
def to_range
|
125
|
+
low..high
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
# Forward referencing is one of those painful problems in programming - if
|
2
|
+
# you try to use something before it's defined, trouble ensues. Using the
|
3
|
+
# ForwardReferencing module and the ForwardReference class can let you
|
4
|
+
# gracefully recover from problems caused by forward references in data and
|
5
|
+
# processing.
|
6
|
+
|
7
|
+
require 'eymiha'
|
8
|
+
|
9
|
+
module Eymiha
|
10
|
+
|
11
|
+
# The ForwardReferencing module can be mixed into a class to allow it to
|
12
|
+
# capture and resolve ForwardReferences.
|
13
|
+
module ForwardReferencing
|
14
|
+
|
15
|
+
# An array containing the set of unresolved forward references.
|
16
|
+
attr_reader :forward_references
|
17
|
+
|
18
|
+
# To be called from the initializer of the includer, this sets up the forward
|
19
|
+
# reference capture and resolution mechanisms.
|
20
|
+
def start_forward_referencing
|
21
|
+
forward_references_clear
|
22
|
+
@had_forward_reference_resolution = false
|
23
|
+
@forward_reference_resolver = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
# To be called when a section of code that could contain a forward reference
|
27
|
+
# is entered. The method returns a newly created ForwardReference with the
|
28
|
+
# given dependency that can be jumped to during resolution.
|
29
|
+
def create_forward_reference(dependency=nil,context=nil)
|
30
|
+
forward_reference = ForwardReference.new(dependency,context)
|
31
|
+
@forward_references << forward_reference
|
32
|
+
forward_reference
|
33
|
+
end
|
34
|
+
|
35
|
+
# To be called when a section of code that could contain a forward reference
|
36
|
+
# has successfully been reached. It is used to remove the ForwardReference
|
37
|
+
# that was created at the start of the section, and asserts that a
|
38
|
+
# resolution was made.
|
39
|
+
def remove_forward_reference(forward_reference=nil)
|
40
|
+
@forward_references.delete forward_reference if
|
41
|
+
(forward_reference.kind_of? ForwardReference)
|
42
|
+
@had_forward_reference_resolution = true
|
43
|
+
end
|
44
|
+
|
45
|
+
# To be called to try to resolve any unresolved ForwardReferences by jumping
|
46
|
+
# to each in turn and retrying the code that caused it. This method repeats
|
47
|
+
# until nothing more is resolved. At that point unresolved forward reference
|
48
|
+
# may still exist, to be possibly resolved by another call to this method
|
49
|
+
# downstream. Prior to continuing to a forward reference, the
|
50
|
+
# establish_forward_reference context method is called with the context that
|
51
|
+
# was provided at the time the forward reference was created to give the
|
52
|
+
# receiver a chance to reset any transcient infromation.
|
53
|
+
def resolve_forward_references
|
54
|
+
forward_references = @forward_references
|
55
|
+
forward_references_clear
|
56
|
+
@had_forward_reference_resolution = false
|
57
|
+
if forward_references.size > 0
|
58
|
+
@forward_reference_resolver ||= callcc {|cont| cont} while
|
59
|
+
(@forward_reference_resolver == nil)
|
60
|
+
forward_reference = forward_references.shift
|
61
|
+
if forward_reference != nil
|
62
|
+
establish_forward_reference_context(forward_reference.context) if
|
63
|
+
respond_to?(:establish_forward_reference_context,true)
|
64
|
+
forward_reference.continuation.call
|
65
|
+
end
|
66
|
+
end
|
67
|
+
@forward_reference_resolver = nil
|
68
|
+
resolve_forward_references if @had_forward_reference_resolution
|
69
|
+
end
|
70
|
+
|
71
|
+
# To be called at the end of a section of code that could contain a forward
|
72
|
+
# reference, it will continue during normal processing and jump back to the
|
73
|
+
# resolve_forward_references method during resolution.
|
74
|
+
def continue_forward_reference_resolution
|
75
|
+
@forward_reference_resolver.call if @forward_reference_resolver
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns a hash of dependencies to arrays of the ForwardReferences that
|
79
|
+
# have them as dependencies.
|
80
|
+
def forward_reference_dependencies
|
81
|
+
dependencies = {}
|
82
|
+
@forward_references.each { |forward_reference|
|
83
|
+
dependency = forward_reference.dependency || "nil"
|
84
|
+
forward_references = dependencies[dependency]
|
85
|
+
dependencies[dependency] = [] if forward_references == nil
|
86
|
+
dependencies[dependency] << forward_reference
|
87
|
+
}
|
88
|
+
dependencies
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns a string indicating the current state of ForwardReferencing.
|
92
|
+
def forward_references_to_s
|
93
|
+
"#{class_name} #{forward_references_remaining} unresolved"
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns the number of unresolved forward references.
|
97
|
+
def forward_references_remaining
|
98
|
+
@forward_references.size
|
99
|
+
end
|
100
|
+
|
101
|
+
# Remove the remaining unresolved forward references.
|
102
|
+
def forward_references_clear
|
103
|
+
@forward_references = []
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
# A ForwardReferencer is simply a class-wrapper for the ForwardReferencing
|
110
|
+
# module. method have been shortened there is reduced potential for conflict
|
111
|
+
# from inheritence than from inclusion or extension.
|
112
|
+
class ForwardReferencer
|
113
|
+
|
114
|
+
include ForwardReferencing
|
115
|
+
|
116
|
+
alias initialize start_forward_referencing
|
117
|
+
alias create create_forward_reference
|
118
|
+
alias remove remove_forward_reference
|
119
|
+
alias resolve resolve_forward_references
|
120
|
+
alias continue continue_forward_reference_resolution
|
121
|
+
alias dependencies forward_reference_dependencies
|
122
|
+
alias to_s forward_references_to_s
|
123
|
+
alias remaining forward_references_remaining
|
124
|
+
alias clear forward_references_clear
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
# A ForwardReference holds a continuation and a dependency, the where and
|
130
|
+
# the why of forward referencing.
|
131
|
+
class ForwardReference
|
132
|
+
|
133
|
+
# Holds the place to jump back to for attempting to resolve a forward
|
134
|
+
# reference.
|
135
|
+
attr_reader :continuation
|
136
|
+
|
137
|
+
# Holds an arbitrary object that indicates why the forward reference
|
138
|
+
# occurred.
|
139
|
+
attr_accessor :dependency
|
140
|
+
|
141
|
+
# Holds an arbitrary object that holds context that can be re-established
|
142
|
+
# to help resolve the forward reference.
|
143
|
+
attr_accessor :context
|
144
|
+
|
145
|
+
# Returns a new instance with a valid continuation, the given dependency
|
146
|
+
# and contextual information.
|
147
|
+
def initialize(dependency=nil,context=nil)
|
148
|
+
@continuation = nil
|
149
|
+
@continuation = callcc{|cont| cont} while (@continuation == nil)
|
150
|
+
@dependency = dependency
|
151
|
+
@context = context
|
152
|
+
end
|
153
|
+
|
154
|
+
# Returns a string indicating the current state of the ForwardReference.
|
155
|
+
def to_s
|
156
|
+
"#{class_name} dependency #{dependency} #{continuation}"
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# Histograms have lots of uses - whenever you need to keep track of the
|
2
|
+
# occurences of items and how many times they've occured, a histogram is
|
3
|
+
# just what's needed.
|
4
|
+
|
5
|
+
module Eymiha
|
6
|
+
|
7
|
+
# An exception thrown when adding Arrays to Histograms that cannot be
|
8
|
+
# meaningfully interpretted.
|
9
|
+
class HistogramException < Exception
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
# A Histogram is a hash whose values are counts of the occurences of the keys.
|
14
|
+
class Histogram < Hash
|
15
|
+
|
16
|
+
# Creates and returns an instance. If arguments are given, they are passed to
|
17
|
+
# the add method to initialize the new instance.
|
18
|
+
def initialize(key=nil,number=1)
|
19
|
+
super()
|
20
|
+
add(key,number) unless key == nil
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the number of occurences of the given key. If an array of keys
|
24
|
+
# is given, the sum of the number of occurences of those keys is returned.
|
25
|
+
def count(check_keys = keys)
|
26
|
+
check_keys = [check_keys] if ! check_keys.kind_of? Array
|
27
|
+
count = 0
|
28
|
+
check_keys.each { |key| count += self[key] if has_key? key }
|
29
|
+
count
|
30
|
+
end
|
31
|
+
|
32
|
+
# Adds the key to the instance if it doesn't already exist, and adds the
|
33
|
+
# specified count to it value. If the key is
|
34
|
+
# * an Array, each member of the array is added. if the member itself is an Array, then if that array has one member, the member is added as a key; if two members, the member is added as a key and a count; otherwise, a HistogramException is thrown.
|
35
|
+
# * another histogram, the keys and counts in the key are added to the instance.
|
36
|
+
def add(key,count=1)
|
37
|
+
if key.kind_of? Array
|
38
|
+
key.each { |member|
|
39
|
+
if member.kind_of? Array
|
40
|
+
if member.size == 1
|
41
|
+
add(member[0])
|
42
|
+
elsif (member.size == 2) && (member[1].kind_of? Fixnum)
|
43
|
+
add(member[0],member[1])
|
44
|
+
else
|
45
|
+
raise HistogramException, "add cannot interpret Array to add"
|
46
|
+
end
|
47
|
+
else
|
48
|
+
add member
|
49
|
+
end
|
50
|
+
}
|
51
|
+
elsif key.kind_of? Histogram
|
52
|
+
key.each_pair { |k,v| add(k,v) }
|
53
|
+
else
|
54
|
+
self[key] = ((value = self[key]) == nil) ? count : value+count
|
55
|
+
end
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the number of keys in the instance.
|
60
|
+
def key_count
|
61
|
+
keys.size
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns a new Histogram containing the elements with occurences greater
|
65
|
+
# than or equal to the given count.
|
66
|
+
def >=(count)
|
67
|
+
result = Histogram.new
|
68
|
+
each_pair { |k,v| result.add(k,v) if v >= count }
|
69
|
+
result
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns a new Histogram containing the elements with occurences greater
|
73
|
+
# than the given count.
|
74
|
+
def >(count)
|
75
|
+
result = Histogram.new
|
76
|
+
each_pair { |k,v| result.add(k,v) if v > count }
|
77
|
+
result
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns a new Histogram containing the elements with occurences less than
|
81
|
+
# or equal to the given count.
|
82
|
+
def <=(count)
|
83
|
+
result = Histogram.new
|
84
|
+
each_pair { |k,v| result.add(k,v) if v <= count }
|
85
|
+
result
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns a new Histogram containing the elements with occurences less than
|
89
|
+
# the given count.
|
90
|
+
def <(count)
|
91
|
+
result = Histogram.new
|
92
|
+
each_pair { |k,v| result.add(k,v) if v < count }
|
93
|
+
result
|
94
|
+
end
|
95
|
+
|
96
|
+
# If count is a number, a new Histogram containing the elements with
|
97
|
+
# occurences equal to the given countis returned. If the count is a
|
98
|
+
# histogram, true is returned if the instance contains the same keys and
|
99
|
+
# values; false otherwise.
|
100
|
+
def ==(count)
|
101
|
+
if count.kind_of? Numeric
|
102
|
+
result = Histogram.new
|
103
|
+
each_pair { |k,v| result.add(k,v) if v >= count }
|
104
|
+
result
|
105
|
+
else
|
106
|
+
super
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Eymiha
|
2
|
+
|
3
|
+
# The MethodicHash is some method_missing magic that uses method names as hash
|
4
|
+
# keys, so hash assignment and lookup appear to be attribute writing and
|
5
|
+
# reading. For instance, if
|
6
|
+
#
|
7
|
+
# mh = MethodicHash.new
|
8
|
+
# mh['four'] = 'iv'
|
9
|
+
# mh[:seven] = 'vii'
|
10
|
+
# mh.eighteen = 'xviii'
|
11
|
+
#
|
12
|
+
# then
|
13
|
+
#
|
14
|
+
# mh['four'] ---> 'iv'
|
15
|
+
# mh[:four] ---> 'iv'
|
16
|
+
# mh.four ---> 'iv'
|
17
|
+
# mh['seven'] ---> 'vii'
|
18
|
+
# mh[:seven] ---> 'vii'
|
19
|
+
# mh.seven ---> 'vii'
|
20
|
+
# mh['eighteen'] ---> 'xviii'
|
21
|
+
# mh[:eighteen] ---> 'xviii'
|
22
|
+
# mh.eighteen ---> 'xviii'
|
23
|
+
#
|
24
|
+
# This allows access to simply declared facts to be embedded in Ruby code and
|
25
|
+
# leverages the possibility of hashing procs.
|
26
|
+
#
|
27
|
+
# Note that if the hash uses anything but strings or symbols as keys, the
|
28
|
+
# magic stands a good chance of failing, raising an error or acting in a
|
29
|
+
# bizarre manner. Note also that methods of the Hash cannot be used as
|
30
|
+
# 'attribute' names.
|
31
|
+
class MethodicHash < Hash
|
32
|
+
|
33
|
+
# Try to look up using a key directly, or if that fails as a string, or as
|
34
|
+
# a symbol as last resort. If a symbol conversion doesn't exists, rescue
|
35
|
+
# with a nil.
|
36
|
+
def [](key)
|
37
|
+
begin
|
38
|
+
super(key) || super(key.to_s) || super(key.to_sym)
|
39
|
+
rescue
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Deletes and returns the key-value pairs from hash whose keys are equal to
|
45
|
+
# key.to_s or key.to_sym. If both key.to_s and key.to_sym are in the hash,
|
46
|
+
# then both values are returned in an Array, respectively. If neither key is
|
47
|
+
# found, the delete is deferred to the Hash.
|
48
|
+
def delete(key,&block)
|
49
|
+
values = [key.to_s, key.to_sym].collect {|k| super(k){ nil } }.compact
|
50
|
+
case values.size
|
51
|
+
when 0 then super(key,&block)
|
52
|
+
when 1 then values[0]
|
53
|
+
when 2 then values
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# A missing method is assummed to be the assignment of a value of a key, or
|
58
|
+
# the lookup of a value with a key.
|
59
|
+
def method_missing(method,*args)
|
60
|
+
string = method.to_s
|
61
|
+
if string[string.length-1,1] == '='
|
62
|
+
self[string[0,string.length-1].to_sym] = args[0]
|
63
|
+
else
|
64
|
+
self[method]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|