goldmine 0.0.4 → 0.9.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.
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