sixarm_ruby_ramp 2.1.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.
@@ -0,0 +1,238 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'yaml'
4
+
5
+ # Hash extensions
6
+
7
+ class Hash
8
+
9
+
10
+ # @return [Boolean] true if size > 0
11
+
12
+ def size?
13
+ size>0
14
+ end
15
+
16
+ # @return [Hash] a new hash sorted by the keys
17
+ #
18
+ # @example
19
+ # h = {"c" => "cherry", "b" => "banana", "a" =>"apple" }
20
+ # h.sort_keys => {"a" => "apple", "b" => "banana", "c" => "cherry"}
21
+
22
+ def sort_by_keys
23
+ Hash[sort]
24
+ end
25
+
26
+
27
+ # Calls block once for each key in hsh, passing the key and value to the block as a two-element array.
28
+ #
29
+ # The keys are sorted.
30
+ #
31
+ # @example
32
+ # h = { "xyz" => "123", "abc" => "789" }
33
+ # h.each_sort {|key, val| ... }
34
+ # => calls the block with "abc" => "789", then with "xyz" => "123"
35
+
36
+ def each_sort
37
+ keys.sort.each{|key| yield key,self[key] }
38
+ end
39
+
40
+
41
+ # Calls block once for each key in hsh,
42
+ # passing the key as a parameter,
43
+ # and updating it in place.
44
+ #
45
+ # @example
46
+ # h = { "a" => "b", "c" => "d" }
47
+ # h.each_key! {|key| key.upcase }
48
+ # h => { "A" => "b", "C" => "d" }
49
+ #
50
+ # @return self
51
+
52
+ def each_key!
53
+ replacements=[]
54
+ keys.each{|key|
55
+ value=self[key]
56
+ key2=yield(key)
57
+ if key===key2
58
+ #nop
59
+ else
60
+ replacements << [key,key2,value]
61
+ end
62
+ }
63
+ replacements.each{|key,key2,value|
64
+ self.delete(key)
65
+ self[key2]=value
66
+ }
67
+ return self
68
+ end
69
+
70
+
71
+ # Calls block once for each key in hsh,
72
+ # passing the key and value as parameters,
73
+ # and updated them in place.
74
+ #
75
+ # @example
76
+ # h = { "a" => "b", "c" => "d" }
77
+ # h.each_pair! {|key,value| key.upcase, value.upcase }
78
+ # h => { "A" => "B", "C" => "D" }
79
+ #
80
+ # @return self.
81
+
82
+ def each_pair!
83
+ replacements=[]
84
+ keys.each{|key|
85
+ value=self[key]
86
+ key2,value2=yield(key,value)
87
+ if key===key2
88
+ if value===value2
89
+ #nop
90
+ else
91
+ self[key]=value2
92
+ end
93
+ else
94
+ replacements << [key,key2,value2]
95
+ end
96
+ }
97
+ replacements.each{|key,key2,value2|
98
+ self.delete(key)
99
+ self[key2]=value2
100
+ }
101
+ return self
102
+ end
103
+
104
+
105
+ # Calls block once for each key in hsh,
106
+ # passing the value as a parameter,
107
+ # and updating it in place.
108
+ #
109
+ # @example
110
+ # h = { "a" => "b", "c" => "d" }
111
+ # h.each_value! {|value| value.upcase }
112
+ # h => { "a" => "B", "c" => "d" }
113
+ #
114
+ # @return self.
115
+
116
+ def each_value!
117
+ keys.each{|key|
118
+ value=self[key]
119
+ value2=yield(value)
120
+ if value===value2
121
+ #nop
122
+ else
123
+ self[key]=yield(value)
124
+ end
125
+ }
126
+ return self
127
+ end
128
+
129
+
130
+ # Calls block once for each key-value pair in hsh,
131
+ # passing the key and value as paramters to the block.
132
+ #
133
+ # @example
134
+ # h = {"a"=>"b", "c"=>"d", "e"=>"f" }
135
+ # h.map_pair{|key,value| key+value }
136
+ # => ["ab","cd","ef"]
137
+
138
+ def map_pair
139
+ keys.map{|key| yield key, self[key] }
140
+ end
141
+
142
+
143
+ # Hash#pivot aggregates values for a hash of hashes,
144
+ # for example to calculate subtotals and groups.
145
+ #
146
+ # Suppose you have data arranged by companies, roles, and headcounts.
147
+ #
148
+ # data = {
149
+ # "Apple" => {"Accountants" => 11, "Designers" => 22, "Developers" => 33},
150
+ # "Goggle" => {"Accountants" => 44, "Designers" => 55, "Developers" => 66},
151
+ # "Microsoft" => {"Accountants" => 77, "Designers" => 88, "Developers" => 99},
152
+ # }
153
+ #
154
+ # To calculate each company's total headcount, you pivot up, then sum:
155
+ #
156
+ # data.pivot(:up,&:sum)
157
+ # => {
158
+ # "Apple"=>66,
159
+ # "Goggle"=>165,
160
+ # "Microsoft"=>264
161
+ # }
162
+ #
163
+ # To calculate each role's total headcount, you pivot down, then sum:
164
+ #
165
+ # data.pivot(:down,&:sum)
166
+ # => {
167
+ # "Accountants"=>132,
168
+ # "Designers"=>165,
169
+ # "Developers"=>198
170
+ # }
171
+ #
172
+ # Generic xxample:
173
+ # h={
174
+ # "a"=>{"x"=>1,"y"=>2,"z"=>3},
175
+ # "b"=>{"x"=>4,"y"=>5,"z"=>6},
176
+ # "c"=>{"x"=>7,"y"=>8,"z"=>9},
177
+ # }
178
+ # h.pivot(:keys) => {"a"=>[1,2,3],"b"=>[4,5,6],"c"=>[7,8,9]}
179
+ # h.pivot(:vals) => {"x"=>[1,4,7],"y"=>[2,5,8],"z"=>[3,6,9]}
180
+ #
181
+ # = Calculating subtotals
182
+ #
183
+ # The pivot method is especially useful for calculating subtotals.
184
+ #
185
+ # @example
186
+ # r = h.pivot(:keys)
187
+ # r['a'].sum => 6
188
+ # r['b'].sum => 15
189
+ # r['c'].sum => 24
190
+ #
191
+ # @example
192
+ # r=h.pivot(:vals)
193
+ # r['x'].sum => 12
194
+ # r['y'].sum => 15
195
+ # r['z'].sum => 18
196
+ #
197
+ # = Block customization
198
+ #
199
+ # You can provide a block that will be called for the pivot items.
200
+ #
201
+ # @example
202
+ # h.pivot(:keys){|items| items.max } => {"a"=>3,"b"=>6,"c"=>9}
203
+ # h.pivot(:keys){|items| items.join("/") } => {"a"=>"1/2/3","b"=>"4/5/6","c"=>"7/8/9"}
204
+ # h.pivot(:keys){|items| items.inject{|sum,x| sum+=x } } => {"a"=>6,"b"=>15,"c"=>24}
205
+ #
206
+ # @example
207
+ # h.pivot(:vals){|items| items.max } => {"a"=>7,"b"=>8,"c"=>9}
208
+ # h.pivot(:vals){|items| items.join("-") } => {"a"=>"1-4-7","b"=>"2-5-8","c"=>"3-6-9"}
209
+ # h.pivot(:vals){|items| items.inject{|sum,x| sum+=x } } => {"a"=>12,"b"=>15,"c"=>18}
210
+
211
+ def pivot(direction='keys',&block)
212
+ a=self.class.new
213
+ direction=direction.to_s
214
+ up=pivot_direction_up?(direction)
215
+ each_pair{|k1,v1|
216
+ v1.each_pair{|k2,v2|
217
+ k = up ? k1 : k2
218
+ a[k]=[] if (a[k]==nil or a[k]=={})
219
+ a[k]<<(v2)
220
+ }
221
+ }
222
+ if block
223
+ a.each_pair{|key,val| a[key]=block.call(val)}
224
+ end
225
+ a
226
+ end
227
+
228
+ protected
229
+
230
+ def pivot_direction_up?(direction_name)
231
+ case direction_name.to_s
232
+ when 'key','keys','up','left','out' then return true
233
+ when 'val','vals','down','right','in' then return false
234
+ else raise ArgumentError.new('Pivot direction must be either: key/keys/up/left/out or val/vals/down/right/in')
235
+ end
236
+ end
237
+
238
+ end
@@ -0,0 +1,26 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Integer extensions
4
+
5
+ class Integer
6
+
7
+ # Syntactic sugar to yield n times to a block.
8
+ #
9
+ # Comparison to Integer#times:
10
+ # Integer#maps is similar to Integer#times except that the output from each
11
+ # call to the block is captured in an array element and that array is
12
+ # returned to the calling code.
13
+ #
14
+ # @return an array of any results
15
+ #
16
+ # @example Generate an array of three random numbers
17
+ # 3.maps{rand}
18
+ # => [0.0248131784304143, 0.814666170190905, 0.15812816258206]
19
+ #
20
+
21
+ def maps
22
+ return (0...self).map{|item| yield item}
23
+ end
24
+
25
+
26
+ end
@@ -0,0 +1,71 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # IO extensions
4
+
5
+ class IO
6
+
7
+
8
+ # Reads the entire file specified by name as individual lines as with IO#readlines,
9
+ # and returns those lines in an array of rows, where each row is an array of fields.
10
+ #
11
+ # @return [Array<Array<String>>] an array of rows, where each row is an array of fields.
12
+ #
13
+ # @example
14
+ # IO.readrows("my.tsv")
15
+ # => [["A1","B1","C1"],["A2","B2","C2"],["A3","B3","C3"]]
16
+ #
17
+ # @param [String] filename
18
+ # @param [Hash] options
19
+ # - Rows are separated by _row_ option, which defaults to Ruby's record separator $/ or "\n"
20
+ # - Cols are separated by _col_ option, which defaults to Ruby's string split separator $; or "\t"
21
+ #
22
+ # @example with options suitable for a file using TSV (Tab Separated Values)
23
+ # IO.readrows("my.tsv", :row=>"\n", :col=>"\t")
24
+ #
25
+ # Note: the col option is sent along to String#split, so can be a string or a regexp.
26
+ #
27
+ # @see
28
+ # - File#readline
29
+ # - File#readlines
30
+ # - File#readrow
31
+
32
+ def IO.readrows(filename, options={})
33
+ row_sep||=options[:row]||$/||"\n"
34
+ col_sep||=options[:col]||$;||"\t"
35
+ return IO.readlines(filename, row_sep).map{|line| line.chomp(row_sep).split(col_sep)}
36
+ end
37
+
38
+
39
+ # Read a line as with IO#readline and return the line as a row of fields.
40
+ #
41
+ # Note: the col option is sent along to String#split, so can be a string or a regexp.
42
+ #
43
+ # @return [Array<String>] fields
44
+ #
45
+ # @param [Hash] options
46
+ # - Rows are separated by _row_ option, which defaults to Ruby's record separator $/ or "\n"
47
+ # - Cols are separated by _col_ option, which defaults to Ruby's string split separator $; or "\t"
48
+ #
49
+ # @example
50
+ # file = File.new("my.tsv")
51
+ # file.readrow() => ["A1","B1","C1"]
52
+ # file.readrow() => ["A2","B2","C2"]
53
+ # file.readrow() => ["A3","B3","C3"]]
54
+ #
55
+ # @example with options suitable for a file using TSV (Tab Separated Values)
56
+ # file = File.new("my.tsv")
57
+ # file.readrow(:row=>"\n", :col=>"\t") => ["A1","B1","C1"]
58
+ # file.readrow(:row=>"\n", :col=>"\t") => ["A2","B2","C2"]
59
+ # file.readrow(:row=>"\n", :col=>"\t") => ["A3","B3","C3"]
60
+ #
61
+ # @see File#readline
62
+ # @see File#readlines
63
+ # @see File#readrows
64
+
65
+ def readrow(options={})
66
+ row_sep||=options[:row]||$/||"\n"
67
+ col_sep||=options[:col]||$;||"\t"
68
+ return readline(row_sep).chomp(row_sep).split(col_sep)
69
+ end
70
+
71
+ end
@@ -0,0 +1,84 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'pp'
3
+ require 'stringio'
4
+
5
+ # Kernel extensions
6
+
7
+ module Kernel
8
+
9
+ # See:
10
+ # - http://www.ruby-forum.com/topic/75258
11
+ # - In 1.9 (Ruby CVS HEAD) there is #__method__ and #__callee__
12
+ # - http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9#l90
13
+ #-
14
+ # Make this fast because its often doing logging & reporting.
15
+ # Inline this and use $1 because it's empirically faster than /1
16
+ #
17
+ # These two methods are always equal:
18
+ # caller_method_name(0) === my_method_name
19
+ #
20
+ # @example
21
+ # def foo
22
+ # puts my_method_name
23
+ # end
24
+ # foo
25
+ # => "foo"
26
+ #
27
+ # @return [String] my method name
28
+
29
+ def my_method_name
30
+ caller[0] =~ /`([^']*)'/ and $1
31
+ end
32
+
33
+
34
+ # See:
35
+ # - http://www.ruby-forum.com/topic/75258
36
+ # - In 1.9 (Ruby CVS HEAD) there is #__method__ and #__callee__
37
+ # - http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9#l90
38
+ #-
39
+ # Make this fast because its often doing logging & reporting.
40
+ # Inline this and use $1 because it's empirically faster than /1
41
+ #
42
+ # These two methods are always equal:
43
+ # caller_method_name(0) === my_method_name
44
+ #
45
+ # @example
46
+ # def foo
47
+ # puts caller_method_name(0)
48
+ # puts caller_method_name(1)
49
+ # end
50
+ # =>
51
+ # "foo"
52
+ # "irb_binding"
53
+ #
54
+ # @return [String] the method name of the caller at the index
55
+
56
+ def caller_method_name(caller_index=0)
57
+ caller[caller_index] =~ /`([^']*)'/ and $1
58
+ end
59
+
60
+
61
+ # Pretty print to a string.
62
+ #
63
+ # Created by Graeme Mathieson.
64
+ #
65
+ # See http://rha7dotcom.blogspot.com/2008/07/ruby-and-rails-how-to-get-pp-pretty.html
66
+ #
67
+ # @example
68
+ # pp_s(["foo","goo"])
69
+ # => "[\"foo\", \"goo\"]\n"
70
+ #
71
+ # @return [String] a pretty print string of the params
72
+
73
+ def pp_s(*objs)
74
+ str = StringIO.new
75
+ objs.each {|obj|
76
+ PP.pp(obj, str)
77
+ }
78
+ str.rewind
79
+ str.read
80
+ end
81
+ module_function :pp_s
82
+
83
+ end
84
+
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Math extensions
4
+
5
+ module Math
6
+
7
+
8
+ # @return [Float] the natural log of _num_
9
+ #
10
+ # @example
11
+ # Math.ln(2.719)
12
+ # => 1.00
13
+
14
+ def Math.ln(num)
15
+ Math.log(num)
16
+ end
17
+
18
+
19
+ # @return [Float] the log of _num_ in base _base_
20
+ #
21
+ # @example
22
+ # Math.logn(10000,10)
23
+ # => 4.00
24
+
25
+ def Math.logn(num,base)
26
+ Math.ln(num)/Math.ln(base)
27
+ end
28
+
29
+
30
+ end
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # NilClass provides an instantiatable object
4
+ # suitable for more careful thorough programming.
5
+
6
+ class NilClass
7
+
8
+ # @return [true]
9
+
10
+ def blank?
11
+ return true
12
+ end
13
+
14
+
15
+ # @return [false]
16
+
17
+ def size?
18
+ return false
19
+ end
20
+
21
+ end
22
+
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Numeric extensions
4
+
5
+ class Numeric
6
+
7
+
8
+ # @return 0 if the given flag is any of: nil, false, 0, [], {}
9
+ #
10
+ # @example
11
+ # 3.if(true) => 3
12
+ # 3.if(false) => 0
13
+ #
14
+
15
+ def if(flag)
16
+ if [nil,false,0,[],{}].include?(flag) then 0 else self end
17
+ end
18
+
19
+
20
+ # @return self if flag is nil, false, 0, [], {}; otherwise return 0.
21
+ #
22
+ # @example
23
+ # 3.unless(true) => 0
24
+ # 3.unless(false) => 3
25
+
26
+ def unless(flag)
27
+ if [nil,false,0,[],{}].include?(flag) then self else 0 end
28
+ end
29
+
30
+
31
+ # @return self as a percent, i.e. * 100 then call round.
32
+ #
33
+ # @example
34
+ # x = 0.12345
35
+ # x.percent => 12
36
+ # x.percent(1) => 12.3
37
+ # x.percent(2) => 12.34
38
+ # x.percent(-1) => 10
39
+
40
+ def percent(ndigits=0)
41
+ (self * 100).round(ndigits)
42
+ end
43
+
44
+ end
@@ -0,0 +1,23 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Object extensions
4
+
5
+ class Object
6
+
7
+ # Syntactic sugar for arrays.
8
+ #
9
+ # Definition:
10
+ # object.in? array === array.include? object
11
+ #
12
+ # @example
13
+ # array=['a','b','c']
14
+ # object='b'
15
+ # object.in? array
16
+ # => true
17
+ #
18
+ # @return [Boolean] true iff this object is included in the array.
19
+ def in?(array)
20
+ array.include?(self)
21
+ end
22
+
23
+ end