class Eco::CSV::Table
Public Class Methods
@param input [Array<Row>, Array<Array>, Eco::CSV::Table
, ::CSV::Table]
- when `Array<Array>` => all `rows` as arrays where first array is the **header**
# File lib/eco/csv/table.rb, line 7 def initialize(input) super(to_rows_array(input)) end
Public Instance Methods
Adds a new column at the end @param header_name [String] header of the new column @return [Eco::CSV::Table] with a new empty column
# File lib/eco/csv/table.rb, line 110 def add_column(header_name) new_col = Array.new(length).unshift(header_name) columns_to_table(columns.push(new_col)) end
@return [Array<Array>] each array is the column header followed by its values
# File lib/eco/csv/table.rb, line 151 def columns to_a.transpose end
Creates a single `Hash` where each key, value is a column (header + values) @note it will override columns with same header name @return [Hash] keys are headers, values are arrays
# File lib/eco/csv/table.rb, line 158 def columns_hash columns.map do |col| [col.first, col[1..-1]] end.to_h end
@return [Eco::CSV::Table]
# File lib/eco/csv/table.rb, line 101 def delete_column(i) csv_cols = columns csv_cols.delete(i) columns_to_table(csv_cols) end
It removes all rows where all columns' values are the same
# File lib/eco/csv/table.rb, line 123 def delete_duplicates! unique_rows = [] self.by_row!.delete_if do |row| unique_rows.any? {|done| equal_rows?(row, done)}.tap do |found| unique_rows << row unless found end end end
@return [Array<String>] list of duplicated header names
# File lib/eco/csv/table.rb, line 53 def duplicated_header_names header = self.headers header.select {|e| header.count(e) > 1}.uniq end
# File lib/eco/csv/table.rb, line 146 def empty? length < 1 end
@param row1 [CSV:Row] row to be compared @param row2 [CSV:Row] row to be compared @param [Boolean] `true` if all values of `row1` are as of `row2`
# File lib/eco/csv/table.rb, line 135 def equal_rows?(row1, row2) row1.fields.zip(row2.fields).all? do |(v1, v2)| v1 == v2 end end
@return [Hash] where keys are the groups and the values a `Eco::CSV::Table`
# File lib/eco/csv/table.rb, line 12 def group_by(&block) rows.group_by(&block).transform_values do |rows| self.class.new(rows) end end
@return [Integer] total number of rows not including the header
# File lib/eco/csv/table.rb, line 142 def length to_a.length - 1 end
@return [Eco::CSV::Table]
# File lib/eco/csv/table.rb, line 29 def merge_same_header_names dups = self.duplicated_header_names out_rows = self.map do |row| row.to_a.each_with_object({}) do |(name, value), out| if dups.include?(name) && out.key?(name) if block_given? yield(value, out[name], name) else # resolve value || out[name] end elsif out.key?(name) out[name] else value end.tap do |final_value| out[name] = final_value end end end self.class.new(out_rows) end
@return [Array<::CSV::Row>]
# File lib/eco/csv/table.rb, line 116 def rows [].tap do |out| self.each {|row| out << row} end end
Slices the selected rows @return [Eco::CSV::Table]
# File lib/eco/csv/table.rb, line 74 def slice(*index) case index.first when Range, Numeric self.class.new(rows.slice(index.first)) else self end end
@return [Eco::CSV::Table]
# File lib/eco/csv/table.rb, line 84 def slice_columns(*index) case index.first when Range, Numeric columns_to_table(columns.slice(index.first)) when String csv_cols = columns csv_cols = index.each_with_object([]) do |name, cols| col = csv_cols.find {|col| col.first == name} cols << col if col end columns_to_table(csv_cols) else self end end
Returns an array of row hashes @note it will override columns with same header
# File lib/eco/csv/table.rb, line 166 def to_a_h rows.map(&:to_h) end
@see to_a_h
# File lib/eco/csv/table.rb, line 171 def to_array_of_hashes to_a_h end
@return [Eco::CSV::Table]
# File lib/eco/csv/table.rb, line 19 def transform_headers header = self.headers cols = self.columns cols.each do |col| col[0] = yield(col.first) end columns_to_table(cols) end
@return [Eco::CSV::Table]
# File lib/eco/csv/table.rb, line 59 def transform_values transformed_rows = rows.map do |row| res = yield(row) case res when Array ::CSV::Row.new(row.headers, res) when ::CSV::Row res end end self.class.new(transformed_rows) end
Private Instance Methods
# File lib/eco/csv/table.rb, line 177 def columns_to_table(columns_array) data = to_rows_array(columns_array.transpose) self.class.new(data) end
# File lib/eco/csv/table.rb, line 182 def to_rows_array(data) case data when ::CSV::Table to_rows_array(data.to_a) when Hash # hash of columns header as key and column array as value rows_arrays = [a.keys].concat(a.values.first.zip(*a.values[1..-1])) to_rows_array(data.keys) when Enumerable data = data.dup.compact return data unless data.count > 0 sample = data.first case sample when ::CSV::Row data when Array headers = data.shift data.map do |arr_row| ::CSV::Row.new(headers, arr_row) end.compact when Hash headers = sample.keys headers_str = headers.map(&:to_s) data.map do |hash| ::CSV::Row.new(headers_str, hash.values_at(*headers)) end.compact else raise "Expected data that can be transformed into Array<::CSV::Row>. Given 'Enumerable' of '#{sample.class}'" end else raise "Input type not supported. Given: #{data.class}" end end