hf.benforeva 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.
- checksums.yaml +7 -0
- data/lib/hf.rb +161 -0
- data/lib/hf/version.rb +3 -0
- metadata +45 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2ddb2a2947592632c60492809e6e40efb98f77c2
|
4
|
+
data.tar.gz: e99e23002cf0a8df391e8ab6a9b786a97212bad1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 62c50f2fcd9177b2406db3ae28048ba31aef46a6aebbd38385dd06a3c3171265de40a7ea62bfd77b99ad11c12462aa7cfe84b0632291ff854295e9ad26954b88
|
7
|
+
data.tar.gz: 87cd7f46064e473c1682ef815bffbe1179e254e500305918eede22efdbfb8a450c19d87c2ade897b99dbd754b0485aa81b0c1a8313761a3ac13ddc482a4d96f6
|
data/lib/hf.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
module HF
|
2
|
+
|
3
|
+
WrongSize = Class.new(StandardError)
|
4
|
+
WrongType = Class.new(StandardError)
|
5
|
+
WrongArgumentType = Class.new(StandardError)
|
6
|
+
|
7
|
+
module ::Enumerable
|
8
|
+
|
9
|
+
SINGLE_SIZE = 1
|
10
|
+
|
11
|
+
# @return [Boolean] true when enum is a 1-tuple or single
|
12
|
+
def single?
|
13
|
+
return true if self.count == SINGLE_SIZE
|
14
|
+
return false
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the only element in a 1-tuple/single.
|
18
|
+
# A more idiomatic and safer accessor than first when
|
19
|
+
# the Enumerator is expected to have only one element.
|
20
|
+
# @raise [WrongSize] when the enumerator is not a 1-tuple
|
21
|
+
# @return [Object] the element in the 1-tuple enumerator
|
22
|
+
def only
|
23
|
+
return self.first if self.single?
|
24
|
+
raise WrongSize, wrong_size_message(self.count, SINGLE_SIZE)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @note Uses HF::Range
|
28
|
+
# Returns the range of the first one-member multiset collecting
|
29
|
+
# the specified value at the given multiplicity. This is a collection
|
30
|
+
# such as [3, 3, 3 ,3], where there is multiple instances of one member.
|
31
|
+
# Formally it is a multiset with only one member.
|
32
|
+
# The default multiplicity returns the range of an mset of arbirtrary size.
|
33
|
+
# The default value is not specified it returns the range of the first mset with distinct values.
|
34
|
+
# @param value [Object] the element in the mset
|
35
|
+
# @param multiplicity [Integer] the number of times value appears in mset
|
36
|
+
# @return [Range] the first range where the subset occurs
|
37
|
+
def find_mset(value, multiplicity=-1)
|
38
|
+
is_multiplicity_negative = multiplicity < 0
|
39
|
+
enums_chunked_on_value = self.chunk{|i| i == value}
|
40
|
+
sub_enums = enums_chunked_on_value.collect{|r| r.last}
|
41
|
+
sub_enums_is_mset =
|
42
|
+
if is_multiplicity_negative
|
43
|
+
enums_chunked_on_value.collect{|r| r.first && not(r.single?) }
|
44
|
+
else
|
45
|
+
enums_chunked_on_value.collect{|r| r.first && (r.last.size >= multiplicity) }
|
46
|
+
end
|
47
|
+
first_mset_chunked_index = sub_enums_is_mset.find_index(true)
|
48
|
+
return Range.new(self.count, self.count, true) if first_mset_chunked_index.nil?
|
49
|
+
first_mset_offset = sub_enums.take(first_mset_chunked_index).flatten.size
|
50
|
+
first_mset_size = is_multiplicity_negative ? sub_enums[first_mset_chunked_index].size : multiplicity
|
51
|
+
Range.new(0, first_mset_size.pred).bump(first_mset_offset)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# @param expected_size [Integer]
|
57
|
+
# @param actual_size [Integer]
|
58
|
+
# @return [String] the message for the WrongSize exception
|
59
|
+
def wrong_size_message(expected_size, actual_size)
|
60
|
+
elm_word = actual_size == 1 ? "element" : "elements"
|
61
|
+
"Enumerator is not a #{expected_size}-tuple. It has #{actual_size} #{elm_word} instead of #{expected_size}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class ::Hash
|
66
|
+
|
67
|
+
DEFAULT_EMBED_AS = nil
|
68
|
+
|
69
|
+
# Add field to hash as is or embedded under a key given by embed_as. Addition
|
70
|
+
# only occurs when field contains data.
|
71
|
+
# @param field [Hash] The fields to add to the hash
|
72
|
+
# @param embed_as [#to_s] The key under which the field should be embedded
|
73
|
+
# in the hash
|
74
|
+
# @return [Hash] replace existing hash with modified hash
|
75
|
+
def add_optional!(field, embed_as: DEFAULT_EMBED_AS)
|
76
|
+
return self.merge!(field) if embed_as.eql?(DEFAULT_EMBED_AS)
|
77
|
+
return self if field.empty?
|
78
|
+
self.merge!({embed_as => field})
|
79
|
+
end
|
80
|
+
|
81
|
+
# Add field to hash as is or embedded under a key given by embed_as. Addition
|
82
|
+
# only occurs when field contains data.
|
83
|
+
# @param field [Hash] The fields to add to the hash
|
84
|
+
# @param embed_as [#to_s] The key under which the field should be embedded
|
85
|
+
# in the hash
|
86
|
+
# @return [Hash] creates a new has with modifications
|
87
|
+
def add_optional(field, embed_as: DEFAULT_EMBED_AS)
|
88
|
+
return self.merge(field) if embed_as.eql?(DEFAULT_EMBED_AS)
|
89
|
+
return self.clone if field.empty?
|
90
|
+
self.merge({embed_as => field})
|
91
|
+
end
|
92
|
+
|
93
|
+
# @param keys [HashKeyArray]
|
94
|
+
# @return [Hash] a Hash containing only the keys given.
|
95
|
+
def slice(*keys)
|
96
|
+
self.select{|k,_| keys.include?(k)}
|
97
|
+
end
|
98
|
+
|
99
|
+
# @param (see #slice)
|
100
|
+
# @return [Hash] a Hash containing none of the keys given
|
101
|
+
def drop(*keys)
|
102
|
+
self.reject{|k,_| keys.include?(k)}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class ::Integer
|
107
|
+
|
108
|
+
# Return an IntegerRange that captures all the values after the integer
|
109
|
+
# @return [IntegerRange] a new Range
|
110
|
+
def after
|
111
|
+
(1 + self)..-1
|
112
|
+
end
|
113
|
+
|
114
|
+
# Return an IntegerRange that captures all the positive values before the integer
|
115
|
+
# @return [IntegerRange] a new Range
|
116
|
+
def before
|
117
|
+
0..(self - 1)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class ::Range
|
122
|
+
|
123
|
+
# Bump the beginning and end of an integer range by n
|
124
|
+
# @param n [Integer] the amount to raise both begin and end by
|
125
|
+
# @return [IntegerRange] a new Range
|
126
|
+
def bump(n)
|
127
|
+
raise(WrongType, wrong_type_message(Integer)) unless self.begin.is_a?(Integer)
|
128
|
+
raise(WrongArgumentType, wrong_argument_type_message(Integer, n.class)) unless n.is_a?(Integer)
|
129
|
+
Range.new(self.begin + n, self.end + n, self.exclude_end?)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Return an IntegerRange that captures all the values after the end of the interval
|
133
|
+
# @return [IntegerRange] a new Range
|
134
|
+
def after
|
135
|
+
raise(WrongType, wrong_type_message(Integer)) unless self.begin.is_a?(Integer)
|
136
|
+
(1 + self.end)..-1
|
137
|
+
end
|
138
|
+
|
139
|
+
# Return an IntegerRange that captures all the values before the beginning of the interval
|
140
|
+
# @return [IntegerRange] a new Range
|
141
|
+
def before
|
142
|
+
raise(WrongType, wrong_type_message(Integer)) unless self.begin.is_a?(Integer)
|
143
|
+
0..(self.begin - 1)
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
# @param expected_type [ClassName]
|
149
|
+
# @return [String] the message for the WrongType exception
|
150
|
+
def wrong_type_message(expected_type)
|
151
|
+
"Range must have #{expected_type} values and not #{self.begin.class}"
|
152
|
+
end
|
153
|
+
|
154
|
+
# @param expected_type [ClassName]
|
155
|
+
# @param actual_type [ClassName]
|
156
|
+
# @return [String] the message for the WrongArgumentType exception
|
157
|
+
def wrong_argument_type_message(expected_type, actual_type)
|
158
|
+
"Argument must be an #{expected_type} and not a #{actual_type}"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/lib/hf/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hf.benforeva
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andre Dickson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-11-08 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email: andrebcdickson@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/hf.rb
|
20
|
+
- lib/hf/version.rb
|
21
|
+
homepage:
|
22
|
+
licenses:
|
23
|
+
- MIT
|
24
|
+
metadata: {}
|
25
|
+
post_install_message:
|
26
|
+
rdoc_options: []
|
27
|
+
require_paths:
|
28
|
+
- lib
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
requirements: []
|
40
|
+
rubyforge_project:
|
41
|
+
rubygems_version: 2.6.14.1
|
42
|
+
signing_key:
|
43
|
+
specification_version: 4
|
44
|
+
summary: ruby extensions by Benforeva
|
45
|
+
test_files: []
|