Class: Eco::CSV::Table

Inherits:
CSV::Table
  • Object
show all
Defined in:
lib/eco/csv/table.rb

Instance Method Summary collapse

Constructor Details

#initialize(input) ⇒ Table

Returns a new instance of Table.

Parameters:

  • input (Array<Row>, Array<Array>, Eco::CSV::Table, ::CSV::Table)
    • when Array<Array> => all rows as arrays where first array is the header


6
7
8
9
10
11
12
# File 'lib/eco/csv/table.rb', line 6

def initialize(input)
  super(to_rows_array(input))
  self.delete_if do |row|
    values = row.fields
    values.all?(&:nil?) || values.map(&:to_s).all?(&:empty?)
  end
end

Instance Method Details

#add_column(header_name, pos: -1)) ⇒ Eco::CSV::Table

Note:

by default it adds it to the end.

Adds a new column at the end

Parameters:

  • header_name (String)

    header of the new column

  • pos (Integer) (defaults to: -1))

    index where to add the column (i.e. 0 for first)

Returns:

Raises:

  • (ArgumentError)


137
138
139
140
141
142
# File 'lib/eco/csv/table.rb', line 137

def add_column(header_name, pos: -1)
  header_name = header_name.to_s.strip
  raise ArgumentError, "header_name can't be blank" if header_name.empty?
  new_col = Array.new(length).unshift(header_name)
  columns_to_table(columns.insert(pos, new_col))
end

#add_index_column(header_name = 'idx', pos: 0) ⇒ Eco::CSV::Table

Note:

by default it adds as a first column

Returns with a new column named name with the row number.

Parameters:

  • header_name (String) (defaults to: 'idx')

    header of the new column

  • pos (Integer) (defaults to: 0)

    index where to add the column (i.e. -1 for last)

Returns:



148
149
150
151
152
153
154
155
# File 'lib/eco/csv/table.rb', line 148

def add_index_column(header_name = 'idx', pos: 0)
  header_name = header_name.to_s.strip
  add_column(header_name, pos: pos).tap do |table|
    table.each.with_index do |row, idx|
      row[header_name] = idx + 2
    end
  end
end

#columnsArray<Array>

Returns each array is the column header followed by its values.

Returns:

  • (Array<Array>)

    each array is the column header followed by its values



193
194
195
# File 'lib/eco/csv/table.rb', line 193

def columns
  to_a.transpose
end

#columns_hashHash

Note:

it will override columns with same header name

Creates a single Hash where each key, value is a column (header + values)

Returns:

  • (Hash)

    keys are headers, values are arrays



200
201
202
203
204
# File 'lib/eco/csv/table.rb', line 200

def columns_hash
  columns.map do |col|
    [col.first, col[1..-1]]
  end.to_h
end

#delete_column(i) ⇒ Eco::CSV::Table

Returns:



126
127
128
129
130
# File 'lib/eco/csv/table.rb', line 126

def delete_column(i)
  csv_cols = columns
  csv_cols.delete(i)
  columns_to_table(csv_cols)
end

#delete_duplicates!Object

It removes all rows where all columns' values are the same



165
166
167
168
169
170
171
172
# File 'lib/eco/csv/table.rb', line 165

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

#duplicated_header_namesArray<String>

Returns list of duplicated header names.

Returns:

  • (Array<String>)

    list of duplicated header names



78
79
80
81
# File 'lib/eco/csv/table.rb', line 78

def duplicated_header_names
  header = self.headers
  header.select {|e| header.count(e) > 1}.uniq
end

#empty?Boolean

Returns:

  • (Boolean)


188
189
190
# File 'lib/eco/csv/table.rb', line 188

def empty?
  length < 1
end

#equal_rows?(row1, row2) ⇒ Boolean

Parameters:

  • row1 (CSV:Row)

    row to be compared

  • row2 (CSV:Row)

    row to be compared

  • `true` (Boolean)

    if all values of row1 are as of row2

Returns:

  • (Boolean)


177
178
179
180
181
# File 'lib/eco/csv/table.rb', line 177

def equal_rows?(row1, row2)
  row1.fields.zip(row2.fields).all? do |(v1, v2)|
    v1 == v2
  end
end

#group_by(&block) ⇒ Hash

Returns where keys are the groups and the values a Eco::CSV::Table.

Returns:

  • (Hash)

    where keys are the groups and the values a Eco::CSV::Table



34
35
36
37
38
# File 'lib/eco/csv/table.rb', line 34

def group_by(&block)
  rows.group_by(&block).transform_values do |rows|
    self.class.new(rows)
  end
end

#lengthInteger

Returns total number of rows not including the header.

Returns:

  • (Integer)

    total number of rows not including the header



184
185
186
# File 'lib/eco/csv/table.rb', line 184

def length
  to_a.length - 1
end

#merge_same_header_namesEco::CSV::Table

Note:

it also offers a way to resolve merge conflicts

When there are headers with the same name, it merges those columns

Returns:



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/eco/csv/table.rb', line 54

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

#nil_blank_cellsEco::CSV::Table

A new table from self where blank strings are have been set to nil

Returns:



29
30
31
# File 'lib/eco/csv/table.rb', line 29

def nil_blank_cells
  self.class.new(self).nil_blank_cells!
end

#nil_blank_cells!Eco::CSV::Table

Note:

assumes there are no repeated header names

It ensures blank strings are set to nil

Returns:



17
18
19
20
21
22
23
24
25
# File 'lib/eco/csv/table.rb', line 17

def nil_blank_cells!
  self.each do |row|
    row.dup.each do |header, value|
      value       = value.to_s.strip
      row[header] = value.empty?? nil : value
    end
  end
  self
end

#rowsArray<::CSV::Row>

Returns:

  • (Array<::CSV::Row>)


158
159
160
161
162
# File 'lib/eco/csv/table.rb', line 158

def rows
  [].tap do |out|
    self.each {|row| out << row}
  end
end

#slice(*index) ⇒ Eco::CSV::Table

Slices the selected rows

Returns:



99
100
101
102
103
104
105
106
# File 'lib/eco/csv/table.rb', line 99

def slice(*index)
  case index.first
  when Range, Numeric
    self.class.new(rows.slice(index.first))
  else
    self
  end
end

#slice_columns(*index) ⇒ Eco::CSV::Table

Returns:



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/eco/csv/table.rb', line 109

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

#to_a_hObject

Note:

it will override columns with same header

Returns an array of row hashes



208
209
210
# File 'lib/eco/csv/table.rb', line 208

def to_a_h
  rows.map(&:to_h)
end

#to_array_of_hashesObject

See Also:



213
214
215
# File 'lib/eco/csv/table.rb', line 213

def to_array_of_hashes
  to_a_h
end

#transform_headersEco::CSV::Table

It allows to rename the header names

Returns:



42
43
44
45
46
47
48
49
# File 'lib/eco/csv/table.rb', line 42

def transform_headers
  header = self.headers
  cols   = self.columns
  cols.each do |col|
    col[0] = yield(col.first)
  end
  columns_to_table(cols)
end

#transform_valuesEco::CSV::Table

Returns:



84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/eco/csv/table.rb', line 84

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