sum_sum 0.0.4 → 0.0.5
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/.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
|