tafel 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/CHANGELOG.txt +5 -0
  2. data/README.md +114 -1
  3. data/lib/tafel.rb +139 -16
  4. data/tafel.gemspec +3 -3
  5. metadata +5 -5
data/CHANGELOG.txt CHANGED
@@ -2,6 +2,11 @@
2
2
  = tafel CHANGELOG.txt
3
3
 
4
4
 
5
+ == tafel 0.3.0 released 2016-05-02
6
+
7
+ - settle on .flatten, .to_vtable and to_htable
8
+
9
+
5
10
  == tafel 0.1.0 released 2016-04-10
6
11
 
7
12
  - initial (empty) release
data/README.md CHANGED
@@ -1,7 +1,120 @@
1
1
 
2
2
  # tafel
3
3
 
4
- # license
4
+ [![Build Status](https://secure.travis-ci.org/jmettraux/tafel.svg)](http://travis-ci.org/jmettraux/tafel)
5
+ [![Gem Version](https://badge.fury.io/rb/tafel.svg)](http://badge.fury.io/rb/tafel)
6
+
7
+ A Ruby library to turn pieces of data into arrays of arrays (tables).
8
+
9
+ ## interface
10
+
11
+ ### Tafel .to_htable .to_h
12
+
13
+ Turns the argument into a table where keys are arrayed horizontally.
14
+
15
+ ```ruby
16
+ require 'tafel'
17
+
18
+ #
19
+ # hash of hashes
20
+
21
+ Tafel.to_h(
22
+ {
23
+ 'USD' => { code: 'USD', change: 1.0, min: 500, status: 'active' },
24
+ 'EUR' => { code: 'EUR', change: 1.07, status: 'active' },
25
+ 'CHF' => { code: 'CHF', change: 1.08, min: 700 }
26
+ }
27
+ )
28
+ # ==>
29
+ [
30
+ [ :key, :code, :change, :min, :status ],
31
+ [ 'USD', 'USD', 1.0, 500, 'active' ],
32
+ [ 'EUR', 'EUR', 1.07, nil, 'active' ],
33
+ [ 'CHF', 'CHF', 1.08, 700, nil ]
34
+ ]
35
+
36
+ #
37
+ # array of hashes
38
+
39
+ Tafel.to_htable(
40
+ [
41
+ { a: 1, b: 2 },
42
+ { a: 3, b: 4, c: 5 },
43
+ { a: 6, c: 7 }
44
+ ]
45
+ )
46
+ # ==>
47
+ [
48
+ [ :a, :b, :c ],
49
+ [ 1, 2, nil ],
50
+ [ 3, 4, 5 ],
51
+ [ 6, nil, 7 ]
52
+ ]
53
+
54
+ #
55
+ # plain hash
56
+
57
+ Tafel.to_htable(
58
+ { a: 3, b: 4, c: 5 }
59
+ )
60
+ # ==>
61
+ [
62
+ [ :a, :b, :c ],
63
+ [ 3, 4, 5 ]
64
+ ]
65
+ ```
66
+
67
+ ### Tafel .to_vtable .to_v
68
+
69
+ Turns the argument into a table where keys are arrayed vertically.
70
+
71
+ It leaves non-array and no-hash instances as is.
72
+
73
+ ```ruby
74
+ require 'tafel'
75
+
76
+ Tafel.to_v(
77
+ { interpreter: 'Leo Ferre', song: { name: "C'est extra", year: 1969 } }
78
+ )
79
+ # ==>
80
+ [
81
+ [ :interpret, 'Leo Ferre' ],
82
+ [ :song, [ [ :name, "C'est extra" ], [ :year, 1969 ] ] ]
83
+ ]
84
+ ```
85
+
86
+ It accepts a limit integer parameter defaulting to -1 (recurse entirely). For example:
87
+
88
+ ```ruby
89
+ Tafel.to_v(
90
+ { interpreter: 'Leo Ferre', song: { name: "C'est extra", year: 1969 } },
91
+ 1
92
+ )
93
+ # ==>
94
+ [
95
+ [ :interpret, 'Leo Ferre' ],
96
+ [ :song, { name: "C'est extra", year: 1969 } ]
97
+ ]
98
+ ```
99
+
100
+ ### Tafel.flatten
101
+
102
+ Turns nested tables into a single table.
103
+
104
+ ```ruby
105
+ require 'tafel'
106
+
107
+ Tafel.flatten(
108
+ [ [ 0, 1 ],
109
+ [ 2, [ [ 3, 4 ], [ 5, 6 ] ] ] ]
110
+ )
111
+ # -->
112
+ [ [ 0, 1, nil ],
113
+ [ 2, 3, 4 ],
114
+ [ nil, 5, 6 ] ]
115
+ ```
116
+
117
+ ## license
5
118
 
6
119
  MIT, see LICENSE.txt
7
120
 
data/lib/tafel.rb CHANGED
@@ -25,35 +25,158 @@
25
25
 
26
26
  module Tafel
27
27
 
28
- VERSION = '0.1.0'
28
+ VERSION = '0.3.0'
29
29
 
30
- def self.turn(data)
30
+ def self.table?(o)
31
31
 
32
- data = to_array(data)
32
+ o.is_a?(Array) && o.all? { |r| r.is_a?(Array) }
33
+ end
34
+
35
+ # .to_vtable: keys are arrayed vertically (y explosion)
36
+ # .to_htable: keys are arrayed horizontally (x explosion)
37
+
38
+ def self.to_vtable(x, limit=-1)
39
+
40
+ return x if limit == 0
41
+
42
+ case x
43
+ when Hash then x.to_a.collect { |k, v| [ k, to_vtable(v, limit - 1) ] }
44
+ when Array then x.collect { |e| [ to_vtable(e) ] }
45
+ else x
46
+ end
47
+ end
48
+
49
+ def self.to_htable(x)
50
+
51
+ kla0 = narrow_class(x)
52
+
53
+ kla1 = nil
54
+ if kla0
55
+ vs = x.respond_to?(:values) ? x.values : x
56
+ kla = narrow_class(vs.first)
57
+ kla1 = vs.all? { |v| kla ? v.is_a?(kla) : false } ? kla : nil
58
+ end
59
+
60
+ #p [ kla0, kla1 ]
61
+ case [ kla0, kla1 ]
62
+ when [ Hash, Hash ] then to_h_hash_hash(x)
63
+ when [ Array, Hash ] then to_h_array_hash(x)
64
+ when [ Hash, nil ] then to_h_hash(x)
65
+ else x
66
+ end
67
+ end
68
+
69
+ class << self
70
+ alias to_v to_vtable
71
+ alias to_h to_htable
72
+ end
73
+
74
+ def self.flatten(table)
75
+
76
+ fail ArgumentError.new('not a table') unless table?(table)
77
+
78
+ flat = true
79
+
80
+ table =
81
+ table.collect { |r|
82
+ r.collect { |c| next c unless table?(c); flat = false; flatten(c) }
83
+ }
84
+
85
+ return table if flat
86
+
87
+ ss = table.collect { |r| r.collect { |c| size(c) } }
88
+
89
+ ss.each do |row|
90
+ maxh = row.collect { |cell| cell[1] }.max
91
+ maxh = maxh < 1 ? 1 : maxh
92
+ row.each { |cell| cell[1] = maxh }
93
+ end
94
+ ss.collect { |row| row.size }.max.times do |x|
95
+ maxw = ss.collect { |row| cell = row[x]; cell ? cell[0] : 1 }.max
96
+ maxw = maxw < 1 ? 1 : maxw
97
+ ss.each { |row| cell = row[x]; cell[0] = maxw if cell }
98
+ end
99
+
100
+ w = ss.first.collect(&:first).reduce(&:+)
101
+ h = ss.collect { |row| row[0].last }.reduce(&:+)
102
+
103
+ a = Array.new(h) { Array.new(w) }
33
104
 
34
- if data.all? { |row| row.is_a?(Array) }
35
- data
36
- elsif data.all? { |row| row.is_a?(Hash) }
37
- turn_array_of_hashes(data)
105
+ iterate(ss) do |x, y, s|
106
+
107
+ left = x > 0 ? ss[y][x - 1] : nil
108
+ above = y > 0 ? ss[y - 1][x] : nil
109
+
110
+ woff = left ? left[2] + left[0] : 0
111
+ hoff = above ? above[3] + above[1] : 0
112
+
113
+ s.push(woff, hoff)
114
+
115
+ copy(a, woff, hoff, table[y][x])
116
+ end
117
+
118
+ a
119
+ end
120
+
121
+ protected # well...
122
+
123
+ def self.size(o)
124
+
125
+ table?(o) ? [ o.collect { |r| r.size }.max, o.size ] : [ 0, 0 ]
126
+ end
127
+
128
+ def self.copy(target, woff, hoff, source)
129
+
130
+ if table?(source)
131
+ iterate(source) { |x, y, v| target[hoff + y][woff + x] = v }
38
132
  else
39
- nil
133
+ target[hoff][woff] = source
40
134
  end
41
135
  end
42
136
 
43
- protected
137
+ def self.iterate(table)
44
138
 
45
- def self.to_array(data)
139
+ table.first.size.times do |x|
140
+ table.size.times do |y|
141
+ yield(x, y, table[y][x])
142
+ end
143
+ end
144
+ end
145
+
146
+ def self.narrow_class(x)
46
147
 
47
- data
48
- #return data.values if data.is_a?(Hash)
49
- #return Array[data]
148
+ return Array if x.is_a?(Array)
149
+ return Hash if x.is_a?(Hash)
150
+ nil
50
151
  end
51
152
 
52
- def self.turn_array_of_hashes(data)
153
+ def self.to_h_hash_hash(h)
154
+
155
+ keys = h.values.inject([ :key ]) { |ks, v| ks.concat(v.keys) }.uniq
156
+ table = [ keys ]
157
+
158
+ h.each do |k, v|
159
+ table << keys[1..-1].inject([ k ]) { |row, key| row << v[key]; row }
160
+ end
161
+
162
+ table
163
+ end
53
164
 
54
- keys = data.inject([]) { |a, row| a.concat(row.keys) }.uniq
165
+ def self.to_h_hash(h)
166
+
167
+ [ h.keys, h.inject([]) { |a, (k, v)| a << v; a } ]
168
+ end
169
+
170
+ def self.to_h_array_hash(a)
171
+
172
+ keys = a.inject([]) { |ks, h| ks.concat(h.keys) }.uniq
173
+ table = [ keys ]
174
+
175
+ a.each do |h|
176
+ table << keys.inject([]) { |row, key| row << h[key]; row }
177
+ end
55
178
 
56
- [ keys ] + data.collect { |row| keys.collect { |k| row[k] } }
179
+ table
57
180
  end
58
181
  end
59
182
 
data/tafel.gemspec CHANGED
@@ -10,13 +10,13 @@ Gem::Specification.new do |s|
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.authors = [ 'John Mettraux' ]
12
12
  s.email = [ 'jmettraux@gmail.com' ]
13
- s.homepage = 'http://github.com/jmettraux/raabro'
13
+ s.homepage = 'http://github.com/jmettraux/tafel'
14
14
  s.rubyforge_project = 'rufus'
15
15
  s.license = 'MIT'
16
- s.summary = 'something to turn data into an array of arrays'
16
+ s.summary = 'something to turn data into arrays of arrays'
17
17
 
18
18
  s.description = %{
19
- Something to turn data (JSON) into an array of arrays (CSV)
19
+ Something to turn data into arrays of arrays (suitable for CSV).
20
20
  }.strip
21
21
 
22
22
  #s.files = `git ls-files`.split("\n")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tafel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.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: 2016-04-09 00:00:00.000000000 Z
12
+ date: 2016-05-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -27,7 +27,7 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: 2.13.0
30
- description: Something to turn data (JSON) into an array of arrays (CSV)
30
+ description: Something to turn data into arrays of arrays (suitable for CSV).
31
31
  email:
32
32
  - jmettraux@gmail.com
33
33
  executables: []
@@ -40,7 +40,7 @@ files:
40
40
  - CHANGELOG.txt
41
41
  - LICENSE.txt
42
42
  - README.md
43
- homepage: http://github.com/jmettraux/raabro
43
+ homepage: http://github.com/jmettraux/tafel
44
44
  licenses:
45
45
  - MIT
46
46
  post_install_message:
@@ -64,5 +64,5 @@ rubyforge_project: rufus
64
64
  rubygems_version: 1.8.23.2
65
65
  signing_key:
66
66
  specification_version: 3
67
- summary: something to turn data into an array of arrays
67
+ summary: something to turn data into arrays of arrays
68
68
  test_files: []