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
13
# File 'lib/eco/csv/table.rb', line 6

def initialize(input)
  super(to_rows_array(input))

  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)


143
144
145
146
147
148
149
# File 'lib/eco/csv/table.rb', line 143

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:



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

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



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

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



209
210
211
212
213
# File 'lib/eco/csv/table.rb', line 209

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

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

Returns:



132
133
134
135
136
# File 'lib/eco/csv/table.rb', line 132

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



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

def delete_duplicates!
  unique_rows = []

  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



82
83
84
85
# File 'lib/eco/csv/table.rb', line 82

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

#empty?Boolean

Returns:

  • (Boolean)


197
198
199
# File 'lib/eco/csv/table.rb', line 197

def empty?
  length < 1
end

#equal_rows?(row_1, row_2) ⇒ 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)


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

def equal_rows?(row_1, row_2)
  row_1.fields.zip(row_2.fields).all? do |(v_1, v_2)|
    v_1 == v_2
  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



36
37
38
39
40
# File 'lib/eco/csv/table.rb', line 36

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



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

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:



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

def merge_same_header_names
  dups     = duplicated_header_names
  out_rows = 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:



31
32
33
# File 'lib/eco/csv/table.rb', line 31

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:



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

def nil_blank_cells!
  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>)


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

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

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

Slices the selected rows

Returns:



105
106
107
108
109
110
111
112
# File 'lib/eco/csv/table.rb', line 105

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:



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/eco/csv/table.rb', line 115

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 {|cl| cl.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



217
218
219
# File 'lib/eco/csv/table.rb', line 217

def to_a_h
  rows.map(&:to_h)
end

#to_array_of_hashesObject

See Also:



222
223
224
# File 'lib/eco/csv/table.rb', line 222

def to_array_of_hashes
  to_a_h
end

#transform_headersEco::CSV::Table

It allows to rename the header names

Returns:



44
45
46
47
48
49
50
51
52
# File 'lib/eco/csv/table.rb', line 44

def transform_headers
  cols = columns

  cols.each do |col|
    col[0] = yield(col.first)
  end

  columns_to_table(cols)
end

#transform_valuesEco::CSV::Table

Returns:



88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/eco/csv/table.rb', line 88

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