crosscounter 0.4.0 → 0.5.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 +4 -4
- data/.travis.yml +1 -0
- data/Gemfile +4 -1
- data/bench/compute.rb +7 -1
- data/crosscounter.gemspec +0 -1
- data/lib/crosscounter/compute.rb +38 -9
- data/lib/crosscounter/util.rb +12 -2
- data/lib/crosscounter/version.rb +1 -1
- data/spec/crosscounter/compute_spec.rb +31 -5
- data/spec/crosscounter/util_spec.rb +11 -0
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1597840a6d492374dda49be70c7037fd43dd7220
|
4
|
+
data.tar.gz: f5631aec3a1ec0469e8bd088e7ddd146fd3fee95
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d0e1f9820f5ca86203fec298bc52f12ab69e083eb31a20e63f99df374ae7078716514e8ddccf17d9713d0fd8940c964c230cea9ae03a35a1233f20fff5ac54b
|
7
|
+
data.tar.gz: 8a98d0599eb8e5b46ef4a0f35ab8f28eff3ca38250f068670b3e7ba2e802fc4d9a39a91bd3fb49580b77f2f8cca55d05b2f03ae0664866648b885239db4914f7
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/bench/compute.rb
CHANGED
@@ -10,6 +10,8 @@ rows = JSON.load(IO.read('bench/rows.json'))
|
|
10
10
|
cols = JSON.load(IO.read('bench/cols.json'))
|
11
11
|
data = JSON.load(IO.read('bench/data.json'))
|
12
12
|
|
13
|
+
sub_cols = { 'answers' => cols['answers'].take(1), 'tags' => cols['tags'].take(2) }
|
14
|
+
|
13
15
|
if ENV['PROFILE']
|
14
16
|
require 'ruby-prof'
|
15
17
|
|
@@ -21,8 +23,12 @@ if ENV['PROFILE']
|
|
21
23
|
printer.print(STDOUT)
|
22
24
|
else
|
23
25
|
Benchmark.bmbm do |x|
|
24
|
-
x.report('compute_all'
|
26
|
+
x.report('compute_all') do
|
25
27
|
Crosscounter::Compute.compute_all(data, rows, cols)
|
26
28
|
end
|
29
|
+
|
30
|
+
x.report('compute_sum') do
|
31
|
+
Crosscounter::Compute.compute_all(data, rows, sub_cols)
|
32
|
+
end
|
27
33
|
end
|
28
34
|
end
|
data/crosscounter.gemspec
CHANGED
data/lib/crosscounter/compute.rb
CHANGED
@@ -4,6 +4,32 @@ module Crosscounter
|
|
4
4
|
module Compute
|
5
5
|
extend self
|
6
6
|
|
7
|
+
def compute_all(enumerable, rows, cols)
|
8
|
+
hashified = enumerable.map { |hash| Util.hashify(hash) }
|
9
|
+
string_cols = Util.stringify(cols)
|
10
|
+
string_rows = Util.stringify(rows)
|
11
|
+
|
12
|
+
string_rows.map! do |row|
|
13
|
+
initial = [row, compute(hashified, row)]
|
14
|
+
|
15
|
+
string_cols.each do |col|
|
16
|
+
initial << compute(hashified, row, col)
|
17
|
+
end
|
18
|
+
|
19
|
+
initial
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def compute_sum(enumerable, rows, cols)
|
24
|
+
hashified = enumerable.map { |hash| Util.hashify(hash) }
|
25
|
+
string_rows = Util.stringify(rows)
|
26
|
+
string_cols = Util.stringify(cols)
|
27
|
+
|
28
|
+
string_rows.map! do |row|
|
29
|
+
computex(hashified, row, string_cols).unshift(row)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
7
33
|
def compute(hashes, prop_a, prop_b = nil)
|
8
34
|
count = 0
|
9
35
|
index = 0
|
@@ -20,19 +46,22 @@ module Crosscounter
|
|
20
46
|
count
|
21
47
|
end
|
22
48
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
initial = [row, compute(setified, row)]
|
49
|
+
def computex(hashes, base_prop, other_props)
|
50
|
+
count = 0
|
51
|
+
cross = 0
|
52
|
+
index = 0
|
53
|
+
length = hashes.length
|
29
54
|
|
30
|
-
|
31
|
-
|
55
|
+
while index < length
|
56
|
+
if hashes[index].member?(base_prop)
|
57
|
+
count += 1
|
58
|
+
cross += 1 if other_props.any? && other_props.all? { |prop| hashes[index].member?(prop) }
|
32
59
|
end
|
33
60
|
|
34
|
-
|
61
|
+
index += 1
|
35
62
|
end
|
63
|
+
|
64
|
+
[count, cross]
|
36
65
|
end
|
37
66
|
end
|
38
67
|
end
|
data/lib/crosscounter/util.rb
CHANGED
@@ -1,17 +1,27 @@
|
|
1
1
|
require 'set'
|
2
2
|
|
3
3
|
module Crosscounter
|
4
|
+
DEFAULT_SEPARATOR = '|'
|
5
|
+
|
4
6
|
module Util
|
5
7
|
extend self
|
6
8
|
|
9
|
+
def separator=(sep)
|
10
|
+
@@separator = sep
|
11
|
+
end
|
12
|
+
|
13
|
+
def separator
|
14
|
+
@@separator ||= DEFAULT_SEPARATOR
|
15
|
+
end
|
16
|
+
|
7
17
|
def hashify(hash)
|
8
18
|
stringify(hash).inject({}) do |memo, key|
|
9
|
-
memo[key] =
|
19
|
+
memo[key] = true
|
10
20
|
memo
|
11
21
|
end
|
12
22
|
end
|
13
23
|
|
14
|
-
def stringify(hash, sep =
|
24
|
+
def stringify(hash, sep = separator)
|
15
25
|
hash.flat_map do |key, value|
|
16
26
|
if value.kind_of?(Enumerable)
|
17
27
|
value.map { |elem| "#{key}#{sep}#{elem}" }
|
data/lib/crosscounter/version.rb
CHANGED
@@ -11,10 +11,10 @@ describe Crosscounter::Compute do
|
|
11
11
|
Set.new(['age-18', 'gender-male'])
|
12
12
|
]
|
13
13
|
|
14
|
-
computer.compute(enumerable, 'age-18').
|
15
|
-
computer.compute(enumerable, 'age-18', 'gender-male').
|
16
|
-
computer.compute(enumerable, 'age-19', 'gender-male').
|
17
|
-
computer.compute(enumerable, 'age-19', 'gender-female').
|
14
|
+
expect(computer.compute(enumerable, 'age-18')).to eq(2)
|
15
|
+
expect(computer.compute(enumerable, 'age-18', 'gender-male')).to eq(2)
|
16
|
+
expect(computer.compute(enumerable, 'age-19', 'gender-male')).to eq(0)
|
17
|
+
expect(computer.compute(enumerable, 'age-19', 'gender-female')).to eq(1)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -32,7 +32,7 @@ describe Crosscounter::Compute do
|
|
32
32
|
{ tags: %w[happy sad mad] }
|
33
33
|
)
|
34
34
|
|
35
|
-
computed.
|
35
|
+
expect(computed).to eq([
|
36
36
|
['age|18', 2, 1, 2, 1],
|
37
37
|
['age|19', 2, 1, 1, 1],
|
38
38
|
['gender|male', 3, 1, 3, 1],
|
@@ -40,7 +40,33 @@ describe Crosscounter::Compute do
|
|
40
40
|
['tags|happy', 2, 2, 1, 1],
|
41
41
|
['tags|sad', 3, 1, 3, 1],
|
42
42
|
['tags|mad', 2, 1, 1, 2]
|
43
|
+
])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '.compute_sum' do
|
48
|
+
it 'tabulates all rows against all columns combined' do
|
49
|
+
enumerable = [
|
50
|
+
{ age: 18, gender: 'male', tags: %w[happy sad] },
|
51
|
+
{ age: 19, gender: 'female', tags: %w[happy mad] },
|
52
|
+
{ age: 18, gender: 'male', tags: %w[mad sad] },
|
53
|
+
{ age: 19, gender: 'male', tags: %w[happy sad] }
|
43
54
|
]
|
55
|
+
|
56
|
+
computed = computer.compute_sum(enumerable,
|
57
|
+
{ age: [18, 19], gender: %w[male female], tags: %w[happy sad mad] },
|
58
|
+
{ tags: %w[happy sad] }
|
59
|
+
)
|
60
|
+
|
61
|
+
expect(computed).to eq([
|
62
|
+
['age|18', 2, 1],
|
63
|
+
['age|19', 2, 1],
|
64
|
+
['gender|male', 3, 2],
|
65
|
+
['gender|female', 1, 0],
|
66
|
+
['tags|happy', 3, 2],
|
67
|
+
['tags|sad', 3, 2],
|
68
|
+
['tags|mad', 2, 0]
|
69
|
+
])
|
44
70
|
end
|
45
71
|
end
|
46
72
|
end
|
@@ -1,6 +1,17 @@
|
|
1
1
|
require 'crosscounter/util'
|
2
2
|
|
3
3
|
describe Crosscounter::Util do
|
4
|
+
describe '.separator=' do
|
5
|
+
after do
|
6
|
+
Crosscounter::Util.separator = Crosscounter::DEFAULT_SEPARATOR
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'sets the separator for future usage' do
|
10
|
+
Crosscounter::Util.separator = '.::.'
|
11
|
+
expect(Crosscounter::Util.separator).to eq('.::.')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
4
15
|
describe '.stringify' do
|
5
16
|
it 'unzips a hash into key-value strings' do
|
6
17
|
expect(Crosscounter::Util.stringify(age: [18, 19, 20])).to eq([
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crosscounter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Parker Selbert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 2.99.0.beta1
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: ruby-prof
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
41
|
description: Functionally create cross tabulations
|
56
42
|
email:
|
57
43
|
- parker@sorentwo.com
|