sum_sum 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/CHANGES.md +10 -1
- data/Gemfile.lock +1 -1
- data/lib/sum_sum.rb +85 -39
- data/lib/sum_sum/version.rb +1 -1
- data/spec/sum_sum_spec.rb +34 -0
- metadata +2 -2
data/CHANGES.md
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
### dev
|
2
2
|
|
3
|
-
[full changelog](http://github.com/yolk/sum_sum/compare/v0.0.
|
3
|
+
[full changelog](http://github.com/yolk/sum_sum/compare/v0.0.5...master)
|
4
|
+
|
5
|
+
### 0.0.5 / 2011-01-27
|
6
|
+
|
7
|
+
[full changelog](http://github.com/yolk/sum_sum/compare/v0.0.4...v0.0.5)
|
8
|
+
|
9
|
+
* Added SumSum#level
|
10
|
+
* Some code cleanup
|
11
|
+
* Added SumSum##total_share
|
12
|
+
* Added some rdoc/yard comments
|
4
13
|
|
5
14
|
### 0.0.4 / 2011-01-27
|
6
15
|
|
data/Gemfile.lock
CHANGED
data/lib/sum_sum.rb
CHANGED
@@ -1,80 +1,126 @@
|
|
1
|
+
# = SumSum
|
2
|
+
#
|
3
|
+
# SumSum allows you to generate simple reports on the count of values in hashes.
|
1
4
|
class SumSum < Hash
|
5
|
+
# @overload initialize(*keys, options = {})
|
6
|
+
# @param [Symbol,String] *args the keys to anaylze on hashes
|
7
|
+
# @param [Hash] options are only used internaly
|
8
|
+
#
|
9
|
+
# @example Create a SumSum to analyze hashes with attributes :gender, :age and :name
|
10
|
+
# SumSum.new(:gender, :age, :name)
|
2
11
|
def initialize(*args)
|
3
|
-
|
4
|
-
@
|
5
|
-
@args = args
|
6
|
-
@count = 0
|
12
|
+
options = args[-1].is_a?(Hash) ? args.pop : {}
|
13
|
+
@key, @parent, @level = options[:key], options[:parent], (options[:level] || 0)
|
14
|
+
@kind_of_children, @args, @count = args[level], args, 0
|
7
15
|
super()
|
8
16
|
end
|
9
|
-
|
10
|
-
attr_reader :
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
attr_reader :kind_of_children, :key, :args, :count, :parent, :level
|
19
|
+
|
20
|
+
# Add a new hash to analyze.
|
21
|
+
#
|
22
|
+
# @param [Hash,#[]] hash the data to add to the SumSum instance
|
23
|
+
# @param [Integer] increase_count_by amount to add to count
|
24
|
+
# @return [SumSum] Returns itself
|
25
|
+
#
|
26
|
+
# @example Add some data
|
27
|
+
# sum_sum.add(:gender => "W", :age => 23, :name => "Nina")
|
28
|
+
# sum_sum.add(:gender => "M", :age => 77, :name => "Carl")
|
29
|
+
# sum_sum.add(:gender => "W", :age => 33, :name => "Nora")
|
30
|
+
def add(hash, increase_count_by=1)
|
31
|
+
@count = @count + increase_count_by
|
15
32
|
unless bottom?
|
16
|
-
|
17
|
-
self[key].
|
33
|
+
key = hash[kind_of_children]
|
34
|
+
self[key] ||= SumSum.new(*args, :parent => self, :key => key, :level => level + 1)
|
35
|
+
self[key].add(hash, increase_count_by)
|
18
36
|
end
|
19
37
|
self
|
20
38
|
end
|
21
|
-
|
39
|
+
|
40
|
+
# Returns share compared to parent
|
41
|
+
#
|
42
|
+
# @return [Float] Returns the share between 0.0 and 1.0
|
43
|
+
#
|
44
|
+
# @example Get share of all (returns alway 1.0)
|
45
|
+
# sum_sum.share
|
46
|
+
# => 1.0
|
47
|
+
# @example Get share of all women compared to all entries (two out of three)
|
48
|
+
# sum_sum["W"].share
|
49
|
+
# => 0.75
|
50
|
+
# @example Get share of all women with age 23 compared to all women entries (one out of two)
|
51
|
+
# sum_sum["W"][23].share
|
52
|
+
# => 0.5
|
22
53
|
def share
|
23
54
|
root? ? 1.0 : count/parent.count.to_f
|
24
55
|
end
|
25
|
-
|
56
|
+
|
57
|
+
# Returns share compared to all entries
|
58
|
+
#
|
59
|
+
# @return [Float] Returns the share between 0.0 and 1.0
|
60
|
+
#
|
61
|
+
# @example Get share of all (returns alway 1.0)
|
62
|
+
# sum_sum.total_share
|
63
|
+
# => 1.0
|
64
|
+
# @example Get share of all women compared to all entries (two out of three)
|
65
|
+
# sum_sum["W"].total_share
|
66
|
+
# => 0.75
|
67
|
+
# @example Get share of all women with age 23 compared to all entries (one out of three)
|
68
|
+
# sum_sum["W"][23].total_share
|
69
|
+
# => 0.3333333
|
70
|
+
def total_share
|
71
|
+
count/root.count.to_f
|
72
|
+
end
|
73
|
+
|
26
74
|
def sort!
|
27
75
|
return self if bottom?
|
28
76
|
values.each(&:sort!)
|
29
77
|
to_a.sort_by{|it| it[1].count}.reverse.tap do |array|
|
30
|
-
clear
|
31
|
-
array.each{|k, v| self[k] = v }
|
78
|
+
clear && array.each{|k, v| self[k] = v }
|
32
79
|
end
|
33
80
|
self
|
34
81
|
end
|
35
|
-
|
82
|
+
|
36
83
|
def root?
|
37
|
-
parent
|
84
|
+
!parent
|
38
85
|
end
|
39
|
-
|
86
|
+
|
40
87
|
def bottom?
|
41
|
-
|
88
|
+
!kind_of_children
|
89
|
+
end
|
90
|
+
|
91
|
+
def root
|
92
|
+
root? ? self : parent.root
|
42
93
|
end
|
43
|
-
|
94
|
+
|
44
95
|
def inspect
|
45
|
-
bottom? ? "#{count}" : "{#{
|
96
|
+
bottom? ? "#{count}" : "{#{kind_of_children}:#{count} #{super.gsub(/^\{|\}$/, "")}}"
|
46
97
|
end
|
47
|
-
|
98
|
+
|
48
99
|
def pretty_print(pp)
|
49
100
|
return pp.text(" #{count}") if bottom?
|
50
101
|
super
|
51
102
|
end
|
52
|
-
|
103
|
+
|
53
104
|
def dump
|
54
105
|
return count if bottom?
|
55
106
|
hash = {}
|
56
107
|
each{ |k, v| hash[k] = v.dump }
|
57
|
-
root? ? [
|
108
|
+
root? ? [args, hash] : hash
|
58
109
|
end
|
59
|
-
|
110
|
+
|
60
111
|
def self.load(data)
|
61
112
|
new(*data[0]).tap do |sum_sum|
|
62
113
|
sum_sum.add_from_dump(data[1])
|
63
114
|
end
|
64
115
|
end
|
65
|
-
|
66
|
-
def add_from_dump(data, hash={},
|
67
|
-
data.each do |
|
68
|
-
hash[
|
69
|
-
|
70
|
-
add_from_dump(
|
71
|
-
add(hash,
|
116
|
+
|
117
|
+
def add_from_dump(data, hash={}, on_level=0)
|
118
|
+
data.each do |k, v|
|
119
|
+
hash[args[on_level]] = k
|
120
|
+
v.is_a?(Hash) ?
|
121
|
+
add_from_dump(v, hash, on_level + 1) :
|
122
|
+
add(hash, v)
|
72
123
|
end
|
73
124
|
end
|
74
|
-
|
75
|
-
private
|
76
|
-
|
77
|
-
def all_args
|
78
|
-
[name] + args
|
79
|
-
end
|
125
|
+
|
80
126
|
end
|
data/lib/sum_sum/version.rb
CHANGED
data/spec/sum_sum_spec.rb
CHANGED
@@ -53,6 +53,18 @@ describe SumSum do
|
|
53
53
|
SumSum.load(sum.dump).dump.should eql(sum.dump)
|
54
54
|
end
|
55
55
|
end
|
56
|
+
|
57
|
+
context "#level" do
|
58
|
+
it "should return 0 on root" do
|
59
|
+
sum.level.should eql(0)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should return correct level on children" do
|
63
|
+
sum[:Browser].level.should eql(1)
|
64
|
+
sum[:Browser][:Firefox].level.should eql(2)
|
65
|
+
sum[:Browser][:Firefox]["3.6.0"].level.should eql(3)
|
66
|
+
end
|
67
|
+
end
|
56
68
|
end
|
57
69
|
|
58
70
|
context "adding multiple hashes" do
|
@@ -155,6 +167,28 @@ describe SumSum do
|
|
155
167
|
sum[:Browser][:Firefox].share.should eql(0.25)
|
156
168
|
end
|
157
169
|
end
|
170
|
+
|
171
|
+
context "#total_share" do
|
172
|
+
it "should return 1.0 on root" do
|
173
|
+
sum.total_share.should eql(1.0)
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should return 0.2 on branch with one out of five" do
|
177
|
+
sum[:Crawler].total_share.should eql(0.2)
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should return 0.2 on branch with one out of five deeper in single" do
|
181
|
+
sum[:Crawler][:GoogleBot].total_share.should eql(0.2)
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should return 0.8 on branch with four out of five" do
|
185
|
+
sum[:Browser].total_share.should eql(0.8)
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should return 0.2 deeper in branch with one out of five" do
|
189
|
+
sum[:Browser][:Firefox].total_share.should eql(0.2)
|
190
|
+
end
|
191
|
+
end
|
158
192
|
|
159
193
|
context "#dump" do
|
160
194
|
it "should output serializable array" do
|