goldmine 0.0.4 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,5 +1,5 @@
1
1
  source :rubygems
2
2
 
3
- group :development do
4
- gem "pry"
5
- end
3
+ gem "minitest", :group => :test
4
+ gem "turn", :group => :test
5
+ gem "pry", :group => [:development, :test]
data/Gemfile.lock CHANGED
@@ -1,16 +1,22 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
+ ansi (1.4.2)
4
5
  coderay (1.0.6)
5
6
  method_source (0.7.1)
7
+ minitest (3.1.0)
6
8
  pry (0.9.9.6)
7
9
  coderay (~> 1.0.5)
8
10
  method_source (~> 0.7.1)
9
11
  slop (>= 2.4.4, < 3)
10
12
  slop (2.4.4)
13
+ turn (0.9.5)
14
+ ansi
11
15
 
12
16
  PLATFORMS
13
17
  ruby
14
18
 
15
19
  DEPENDENCIES
20
+ minitest
16
21
  pry
22
+ turn
data/Rakefile CHANGED
@@ -1,9 +1,11 @@
1
1
  require 'rake'
2
2
  require 'rake/testtask'
3
- require 'rake/rdoctask'
3
+ require 'rdoc/task'
4
+ require 'bundler'
5
+ Bundler.require :development, :test
4
6
 
5
7
  Rake::TestTask.new(:test) do |t|
6
- t.test_files = FileList['test/*_test.rb']
8
+ t.test_files = FileList['test/test_*.rb']
7
9
  end
8
10
 
9
11
  task 'test:units' => ['test'] do
data/lib/goldmine.rb CHANGED
@@ -1,7 +1,49 @@
1
1
  require "rubygems"
2
2
 
3
+ # Goldmine brings pivot table behavior to Arrays.
3
4
  module Goldmine
5
+
6
+ # Extends Array with a pivot method.
4
7
  module ArrayMiner
8
+
9
+ # Pivots the Array into a Hash of mined data.
10
+ # Think of it as creating a pivot table or perhaps an OLAP cube.
11
+ #
12
+ # @example Simple pivot
13
+ # list = [1,2,3,4,5,6,7,8,9]
14
+ # data = list.pivot { |i| i < 5 }
15
+ #
16
+ # # resulting data
17
+ # # {
18
+ # # true => [1, 2, 3, 4],
19
+ # # false => [5, 6, 7, 8, 9]
20
+ # # }
21
+ #
22
+ # @example Named pivot
23
+ # list = [1,2,3,4,5,6,7,8,9]
24
+ # data = list.pivot("less than 5") { |i| i < 5 }
25
+ #
26
+ # # resulting data
27
+ # # {
28
+ # # { "less than 5" => true } => [1, 2, 3, 4],
29
+ # # { "less than 5" => false } => [5, 6, 7, 8, 9]
30
+ # # }
31
+ #
32
+ # @example Chained pivot
33
+ # list = [1,2,3,4,5,6,7,8,9]
34
+ # data = list.pivot { |i| i < 5 }.pivot { |i| i % 2 == 0 }
35
+ #
36
+ # # resulting data
37
+ # {
38
+ # [true, false] => [1, 3],
39
+ # [true, true] => [2, 4],
40
+ # [false, false] => [5, 7, 9],
41
+ # [false, true] => [6, 8]
42
+ # }
43
+ #
44
+ # @param [String] name The named of the pivot.
45
+ # @yield [Object] Yields once for each item in the Array
46
+ # @return [Hash] The pivoted Hash of data.
5
47
  def pivot(name=nil, &block)
6
48
  reduce({}) do |memo, item|
7
49
  value = yield(item)
@@ -22,8 +64,31 @@ module Goldmine
22
64
  end
23
65
  end
24
66
 
67
+ # Extends Hash with a pivot method.
25
68
  module HashMiner
69
+
26
70
  attr_accessor :goldmine
71
+
72
+ # Further pivots the Hash into mined data.
73
+ # This method is what enables the pivot method chaining.
74
+ #
75
+ # @example Chained pivot
76
+ # list = [1,2,3,4,5,6,7,8,9]
77
+ # data = list.pivot { |i| i < 5 }.pivot { |i| i % 2 == 0 }
78
+ #
79
+ # # resulting data
80
+ # {
81
+ # [true, false] => [1, 3],
82
+ # [true, true] => [2, 4],
83
+ # [false, false] => [5, 7, 9],
84
+ # [false, true] => [6, 8]
85
+ # }
86
+ #
87
+ # @note This method should not be called directly. Call Array#pivot instead.
88
+ #
89
+ # @param [String] name The named of the pivot.
90
+ # @yield [Object] Yields once for each item in the Array
91
+ # @return [Hash] The pivoted Hash of data.
27
92
  def pivot(name=nil, &block)
28
93
  return self unless goldmine
29
94
  reduce({}) do |memo, item|
@@ -34,7 +99,8 @@ module Goldmine
34
99
  k = { block.to_s => k } unless k.is_a?(Hash)
35
100
  new_key = key.merge(k)
36
101
  else
37
- new_key = [key, k]
102
+ new_key = key.push(k) if key.is_a?(Array)
103
+ new_key ||= [key, k]
38
104
  end
39
105
  memo[new_key] = v
40
106
  end
@@ -43,16 +109,26 @@ module Goldmine
43
109
  end
44
110
  end
45
111
 
112
+ # Assigns a key/value pair to the Hash.
113
+ # @param [String] name The name of a pivot (can be null).
114
+ # @param [Object] key The key to use.
115
+ # @param [Object] value The value to assign
116
+ # @return [Object] The result of the assignment.
46
117
  def assign_mined(name, key, value)
47
- mine_key = goldmine_key(name, key)
48
- self[mine_key] ||= []
49
- self[goldmine_key(name, key)] << value
118
+ goldmine_key = goldmine_key(name, key)
119
+ self[goldmine_key] ||= []
120
+ self[goldmine_key] << value
50
121
  end
51
122
 
123
+ # Creates a key for a pivot-name/key combo.
124
+ # @param [String] name The name of a pivot (can be null).
125
+ # @param [Object] key The key to use.
126
+ # @return [Object] The constructed key.
52
127
  def goldmine_key(name, key)
53
- mine_key = { name => key } if name
54
- mine_key ||= key
128
+ goldmine_key = { name => key } if name
129
+ goldmine_key ||= key
55
130
  end
131
+
56
132
  end
57
133
  end
58
134
 
@@ -0,0 +1,105 @@
1
+ require "test/unit"
2
+ require "turn"
3
+ require File.join(File.dirname(__FILE__), "..", "lib", "goldmine")
4
+
5
+ class TestGoldmine < MiniTest::Unit::TestCase
6
+
7
+ def test_simple_pivot
8
+ list = [1,2,3,4,5,6,7,8,9]
9
+ data = list.pivot { |i| i < 5 }
10
+
11
+ expected = {
12
+ true => [1, 2, 3, 4],
13
+ false => [5, 6, 7, 8, 9]
14
+ }
15
+
16
+ assert_equal expected, data
17
+ end
18
+
19
+ def test_named_pivot
20
+ list = [1,2,3,4,5,6,7,8,9]
21
+ data = list.pivot("less than 5") { |i| i < 5 }
22
+
23
+ expected = {
24
+ { "less than 5" => true } => [1, 2, 3, 4],
25
+ { "less than 5" => false } => [5, 6, 7, 8, 9]
26
+ }
27
+
28
+ assert_equal expected, data
29
+ end
30
+
31
+ def test_pivot_of_list_values
32
+ list = [
33
+ { :name => "one", :list => [1] },
34
+ { :name => "two", :list => [1, 2] },
35
+ { :name => "three", :list => [1, 2, 3] },
36
+ { :name => "four", :list => [1, 2, 3, 4] },
37
+ ]
38
+ data = list.pivot { |record| record[:list] }
39
+
40
+ expected = {
41
+ 1 => [ { :name => "one", :list => [1] },
42
+ { :name => "two", :list => [1, 2] },
43
+ { :name => "three", :list => [1, 2, 3] },
44
+ { :name => "four", :list => [1, 2, 3, 4] } ],
45
+ 2 => [ { :name => "two", :list => [1, 2] },
46
+ { :name => "three", :list => [1, 2, 3] },
47
+ { :name => "four", :list => [1, 2, 3, 4] } ],
48
+ 3 => [ { :name => "three", :list => [1, 2, 3] },
49
+ { :name => "four", :list => [1, 2, 3, 4] } ],
50
+ 4 => [ { :name => "four", :list => [1, 2, 3, 4] } ]
51
+ }
52
+
53
+ assert_equal expected, data
54
+ end
55
+
56
+ def test_chained_pivots
57
+ list = [1,2,3,4,5,6,7,8,9]
58
+ data = list.pivot { |i| i < 5 }.pivot { |i| i % 2 == 0 }
59
+
60
+ expected = {
61
+ [true, false] => [1, 3],
62
+ [true, true] => [2, 4],
63
+ [false, false] => [5, 7, 9],
64
+ [false, true] => [6, 8]
65
+ }
66
+
67
+ assert_equal expected, data
68
+ end
69
+
70
+ def test_deep_chained_pivots
71
+ list = [1,2,3,4,5,6,7,8,9]
72
+ data = list.pivot("a") { |i| i < 3 }.pivot("b") { |i| i < 6 }.pivot("c") { |i| i < 9 }.pivot("d") { |i| i % 2 == 0 }.pivot("e") { |i| i % 3 == 0 }
73
+
74
+ expected1 = {
75
+ {"a"=>true, "b"=>true, "c"=>true, "d"=>false, "e"=>false}=>[1],
76
+ {"a"=>true, "b"=>true, "c"=>true, "d"=>true, "e"=>false}=>[2],
77
+ {"a"=>false, "b"=>true, "c"=>true, "d"=>false, "e"=>true}=>[3],
78
+ {"a"=>false, "b"=>true, "c"=>true, "d"=>false, "e"=>false}=>[5],
79
+ {"a"=>false, "b"=>true, "c"=>true, "d"=>true, "e"=>false}=>[4],
80
+ {"a"=>false, "b"=>false, "c"=>true, "d"=>true, "e"=>true}=>[6],
81
+ {"a"=>false, "b"=>false, "c"=>true, "d"=>true, "e"=>false}=>[8],
82
+ {"a"=>false, "b"=>false, "c"=>true, "d"=>false, "e"=>false}=>[7],
83
+ {"a"=>false, "b"=>false, "c"=>false, "d"=>false, "e"=>true}=>[9]
84
+ }
85
+
86
+ assert_equal expected1, data
87
+ end
88
+
89
+ def test_named_chained_pivots
90
+ list = [1,2,3,4,5,6,7,8,9]
91
+ data = list.pivot("less than 5") { |i| i < 5 }.pivot("divisible by 2") { |i| i % 2 == 0 }
92
+
93
+ expected = {
94
+ { "less than 5" => true, "divisible by 2" => false } => [1, 3],
95
+ { "less than 5" => true, "divisible by 2" => true} => [2, 4],
96
+ { "less than 5" => false, "divisible by 2" => false} => [5, 7, 9],
97
+ { "less than 5" => false, "divisible by 2" => true} => [6, 8]
98
+ }
99
+
100
+ assert_equal expected, data
101
+ end
102
+
103
+
104
+
105
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: goldmine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.9.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-19 00:00:00.000000000 Z
12
+ date: 2012-06-20 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: ! ' Goldmine allows you to apply pivot table logic to any list for
15
15
  powerful data mining capabilities.
@@ -26,6 +26,7 @@ files:
26
26
  - Gemfile.lock
27
27
  - Rakefile
28
28
  - README.md
29
+ - test/test_goldmine.rb
29
30
  homepage: http://hopsoft.github.com/goldmine/
30
31
  licenses:
31
32
  - MIT