table_transform 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ tabletransform
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.2.2
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
data/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ # TableTransform change log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ TableTransform is still in pre-release state. This means that its APIs and behavior are subject to breaking changes without deprecation notices. Until 1.0, version numbers will follow a [Semver][]-ish `0.y.z` format, where `y` is incremented when new features or breaking changes are introduced, and `z` is incremented for lesser changes or bug fixes.
6
+
7
+ ## [Unreleased]
8
+
9
+ ## 0.1.0 (2016-02-10)
10
+
11
+ * Initial release including Table
12
+
13
+ [Semver]: http://semver.org
14
+ [Unreleased]: https://github.com/jonas-lantto/table_transform/compare/v0.1.0...HEAD
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in table_transform.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Jonas Lantto
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # TableTransform
2
+ [![Gem Version](https://badge.fury.io/rb/table_transform.svg)](http://badge.fury.io/rb/table_transform)
3
+ [![Build Status](https://travis-ci.org/jonas-lantto/table_transform.svg)](https://travis-ci.org/jonas-lantto/table_transform)
4
+ [![Code Climate](https://codeclimate.com/github/jonas-lantto/table_transform/badges/gpa.svg)](https://codeclimate.com/github/jonas-lantto/table_transform)
5
+
6
+ Utility to work with csv type data in a name safe environment with utilities to transform data
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'table_transform'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install table_transform
21
+
22
+ ## Usage
23
+
24
+ ### Create and populate
25
+
26
+ # Create from file
27
+ t = TableTransform::Table::create_from_file('data.csv')
28
+
29
+ # Create empty table with given column names
30
+ t = TableTransform::Table::create_empty(%w(Col1 Col2))
31
+ t << {'Col1' => 1, 'Col2' => 2}
32
+
33
+ # Create from an array of arrays. First row column names
34
+ data = [ %w(Name Age), %w(Jane 22)]
35
+ t = TableTransform::Table.new(data)
36
+
37
+ ### Work with the table
38
+ # Add a new column to the far right
39
+ t.add_column('NameLength'){|row| row['Name'].size}
40
+
41
+ # Change values in existing column
42
+ t.change_column('Age'){|row| row['Age'].to_i}
43
+
44
+ # Will remove given columns. One or several can be specified.
45
+ t.delete_column('Name', 'Address')
46
+
47
+ # Create a new Table with given column in specified order
48
+ t.extract(%w(Length Name))
49
+
50
+ # Filter table
51
+ t.filter{|row| row['Age].to_i > 20}
52
+
53
+ # Adds rows of two tables with same header
54
+ t1 = TableTransform::Table::create_empty(%w(Col1 Col2))
55
+ t2 = TableTransform::Table::create_empty(%w(Col1 Col2))
56
+ t3 = t1 + t2
57
+
58
+ # Export as array
59
+ t.to_a
60
+
61
+ ## Contributing
62
+
63
+ Bug reports and pull requests are welcome on [GitHub](https://github.com/jonas-lantto/table_transform).
64
+
65
+
66
+ ## License
67
+
68
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
69
+
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
3
+ require 'rake/testtask'
4
+
5
+ task :default => [:test]
6
+
7
+ desc 'Run all tests'
8
+ Rake::TestTask.new(:test) { |t|
9
+ t.libs << 'lib'
10
+ t.test_files = FileList['test/*_test.rb']
11
+ t.verbose = true
12
+ t.warning = true
13
+ }
@@ -0,0 +1,3 @@
1
+ require 'table_transform/version'
2
+ require 'table_transform/table'
3
+
@@ -0,0 +1,140 @@
1
+ require 'csv'
2
+
3
+ module TableTransform
4
+ module Util
5
+ def self.get_col_index(col_name, data)
6
+ data[col_name] || (raise "No column with name '#{col_name}' exists")
7
+ end
8
+ end
9
+
10
+ class Table
11
+ def self.create_from_file(file_name, sep = ',')
12
+ rows = CSV.read(file_name, { :col_sep => sep })
13
+ raise "'#{file_name}' contains no data" if rows.empty?
14
+
15
+ Table.new(rows)
16
+ end
17
+
18
+ def self.create_empty(header)
19
+ raise 'Table header need to be array' unless header.is_a? Array
20
+ raise 'Table, No header defined' if header.empty?
21
+ Table.new([header])
22
+ end
23
+
24
+ # @throws if column names not unique
25
+ # @throws if column size for each row match
26
+ def initialize(rows)
27
+ @data_rows = rows.clone
28
+ @header = @data_rows.shift
29
+ @column_indexes = create_column_name_binding(@header)
30
+
31
+ #validate header uniqueness
32
+ dup = @header.select{ |e| @header.count(e) > 1 }.uniq
33
+ raise "Column #{dup.map{|x| "'#{x}'"}.join(' and ')} not unique" if dup.size > 0
34
+
35
+ #validate column size
36
+ @data_rows.each_with_index {|x, index| raise "Column size mismatch. On row #{index+1}. Size #{x.size} expected to be #{@header.size}" if @header.size != x.size}
37
+ end
38
+
39
+ def << (hash_values)
40
+ @data_rows << create_row(hash_values)
41
+ self
42
+ end
43
+
44
+ # Add two tables
45
+ # @throws if header do not match
46
+ def +(table)
47
+ t2 = table.to_a
48
+ t2_header = t2.shift
49
+ raise 'Tables cannot be added due to header mismatch' if @header != t2_header
50
+ TableTransform::Table.new(self.to_a + t2)
51
+ end
52
+
53
+ def each_row
54
+ @data_rows.each{|x|
55
+ yield Row.new(@column_indexes, x)
56
+ }
57
+ end
58
+
59
+ # @returns array of data arrays including header row
60
+ def to_a
61
+ res = @data_rows.clone
62
+ res.unshift @header
63
+ end
64
+
65
+ # @returns new table with specified columns specified in given header
66
+ def extract(header)
67
+ selected_cols = header.inject([]) { |res, c| res << Util::get_col_index(c, @column_indexes) }
68
+ Table.new( @data_rows.inject([header]) {|res, row| (res << row.values_at(*selected_cols))} )
69
+ end
70
+
71
+ # @returns new table with rows that match given block
72
+ def filter
73
+ Table.new( @data_rows.select {|row| yield Row.new(@column_indexes, row)}.unshift @header.clone )
74
+ end
75
+
76
+ #adds a column with given name to the far right of the table
77
+ #@throws if given column name already exists
78
+ def add_column(name)
79
+ raise "Column '#{name}' already exists" if @header.include?(name)
80
+ @header << name
81
+ @data_rows.each{|x|
82
+ x << (yield Row.new(@column_indexes, x))
83
+ }
84
+ @column_indexes[name] = @column_indexes.size
85
+ self # enable chaining
86
+ end
87
+
88
+ def change_column(name)
89
+ index = Util::get_col_index(name, @column_indexes)
90
+ @data_rows.each{|r|
91
+ r[index] = yield Row.new(@column_indexes, r)
92
+ }
93
+ self # enable chaining
94
+ end
95
+
96
+ def delete_column(*names)
97
+ delete_indexes = names.inject([]){|res, n| res << Util::get_col_index(n, @column_indexes)}
98
+ delete_indexes.sort!.reverse!
99
+ delete_indexes.each{|i| @header.delete_at(i)}
100
+
101
+ selected_cols = @header.inject([]) { |res, c| res << Util::get_col_index(c, @column_indexes) }
102
+ @data_rows.map!{|row| row.values_at(*selected_cols)}
103
+
104
+ @column_indexes = create_column_name_binding(@header)
105
+ self
106
+ end
107
+
108
+ class Row
109
+
110
+ def initialize(cols, row)
111
+ @cols = cols #column name and index in row
112
+ @row = row #Specific row
113
+ end
114
+
115
+ # @returns row value with column name or empty string if it does not exist
116
+ # @throws exception if column name does not exist
117
+ def [](column_name)
118
+ index = Util::get_col_index(column_name, @cols)
119
+ Cell.new @row[ index ].to_s || ''
120
+ end
121
+
122
+ end
123
+
124
+ class Cell < String
125
+ # @returns true if this cell includes any of the given values in list
126
+ def include_any?(list)
127
+ list.inject(false){|res, x| res | (self.include? x)}
128
+ end
129
+ end
130
+
131
+ private
132
+ def create_column_name_binding(header_row)
133
+ header_row.map.with_index{ |x, i| [x, i] }.to_h
134
+ end
135
+
136
+ def create_row(hash_values)
137
+ @header.inject([]) { |row, col| row << hash_values.fetch(col){raise "Value for column '#{col}' could not be found"} }
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,3 @@
1
+ module TableTransform
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'table_transform/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'table_transform'
8
+ spec.version = TableTransform::VERSION
9
+ spec.authors = ['Jonas Lantto']
10
+ spec.email = ['j@lantto.net']
11
+
12
+ spec.summary = %q{Utility to work with csv type data in a name safe environment with utilities to transform data}
13
+ spec.description = %q{}
14
+ spec.homepage = 'https://github.com/jonas-lantto/table_transform'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.10'
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'minitest', '~> 5.0'
25
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: table_transform
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jonas Lantto
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-02-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: ''
56
+ email:
57
+ - j@lantto.net
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".codeclimate.yml"
63
+ - ".gitignore"
64
+ - ".rubocop.yml"
65
+ - ".ruby-gemset"
66
+ - ".ruby-version"
67
+ - ".travis.yml"
68
+ - CHANGELOG.md
69
+ - Gemfile
70
+ - LICENSE.txt
71
+ - README.md
72
+ - Rakefile
73
+ - lib/table_transform.rb
74
+ - lib/table_transform/table.rb
75
+ - lib/table_transform/version.rb
76
+ - table_transform.gemspec
77
+ homepage: https://github.com/jonas-lantto/table_transform
78
+ licenses:
79
+ - MIT
80
+ metadata: {}
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 2.4.8
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: Utility to work with csv type data in a name safe environment with utilities
101
+ to transform data
102
+ test_files: []