Class: TrueTable

Inherits:
Array
  • Object
show all
Defined in:
lib/true_table.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.from_csv(csv_string, options = {}) ⇒ TrueTable

Loads a CSV string

Examples:

csv = "id,name\n1,Harry\n2,Lloyd"
table = TrueTable.load_csv csv, converters: [:date, :numeric]

Parameters:

  • csv_string (String)

    CSV string.

  • options (Hash) (defaults to: {})

    options to forward to the CSV class.

Returns:



15
16
17
18
19
20
21
# File 'lib/true_table.rb', line 15

def from_csv(csv_string, options = {})
  default_options = { headers: true, converters: :numeric, header_converters: :symbol }
  csv = CSV.new csv_string, **default_options.merge(options)
  new.tap do |table|
    csv.each { |row| table << row.to_h }
  end
end

.load_csv(path, options = {}) ⇒ TrueTable

Loads a CSV file

Examples:

table = TrueTable.from_csv "sample.csv", converters: [:date, :numeric]

Parameters:

  • path (String)

    the path to the CSV file.

  • options (Hash) (defaults to: {})

    options to forward to the CSV class.

Returns:



32
33
34
# File 'lib/true_table.rb', line 32

def load_csv(path, options = {})
  from_csv File.read(path), options
end

Instance Method Details

#+(other) ⇒ Object

Combines table with other and returns a new one



38
39
40
41
42
# File 'lib/true_table.rb', line 38

def +(other)
  result = self.class.new
  each_row { |row, i| result << row.merge(other[i]) }
  result
end

#-(cols) ⇒ Object

Returns a new table without the specified columns



45
46
47
48
49
50
# File 'lib/true_table.rb', line 45

def -(cols)
  keep_keys = headers - cols
  result = self.class.new
  each_row { |row, i| result << row.slice(*keep_keys) }
  result
end

#[](key) ⇒ Object Also known as: row

Returns a row or a column



53
54
55
# File 'lib/true_table.rb', line 53

def [](key)
  key.is_a?(Symbol) ? col(key) : super
end

#[]=(key, value) ⇒ Object

Adds or updates a row or a column



58
59
60
# File 'lib/true_table.rb', line 58

def []=(key, value)
  key.is_a?(Symbol) ? add_col(key.to_sym, value) : super
end

#cloneObject

Returns a deep copy of self



63
64
65
# File 'lib/true_table.rb', line 63

def clone
  self.class.new map(&:clone)
end

#col(key) ⇒ Object

Returns a column as Array



68
69
70
# File 'lib/true_table.rb', line 68

def col(key)
  map { |row| row[key] }
end

#colsObject

Returns a hash of columns



73
74
75
76
77
# File 'lib/true_table.rb', line 73

def cols
  result = {}
  each_col { |col, header| result[header] = col }
  result
end

#compactObject

Returns a copy of self without rows that contain nil in any column



80
81
82
# File 'lib/true_table.rb', line 80

def compact
  dup.compact!
end

#compact!Object

Removes rows with nil in any column



85
86
87
# File 'lib/true_table.rb', line 85

def compact!
  delete_if { |row| row.values.include? nil }
end

#delete_at(index) ⇒ Object Also known as: delete_col, delete_row

Delete a row or a column in place and returns the deleted row/column



90
91
92
93
94
95
96
97
98
99
# File 'lib/true_table.rb', line 90

def delete_at(index)
  if index.is_a?(Symbol) || index.is_a?(String)
    result = self[index]
    return nil unless result
    each_row { |row, i| row.delete index }
    result
  else
    super
  end
end

#difference(*others) ⇒ Object

Returns a table with different rows



104
105
106
# File 'lib/true_table.rb', line 104

def difference(*others)
  self.class.new super
end

#dig(*indexes) ⇒ Object

Extracts nested value. Accepts row, column or column, row



109
110
111
112
113
114
115
116
# File 'lib/true_table.rb', line 109

def dig(*indexes)
  key = indexes.shift
  if key.is_a?(Symbol)
    col(key.to_sym).dig *indexes
  else
    row(key).dig *indexes
  end
end

#drop(*args) ⇒ Object

Returns a new table without the first N rows



119
120
121
# File 'lib/true_table.rb', line 119

def drop(*args)
  self.class.new super
end

#drop_while(*args) ⇒ Object

Returns a new table with rows until the block returns false



124
125
126
# File 'lib/true_table.rb', line 124

def drop_while(*args)
  self.class.new super
end

#each_colObject

Iterates over columns



129
130
131
# File 'lib/true_table.rb', line 129

def each_col
  headers.each { |header| yield col(header), header }
end

#fetch(key, *default) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/true_table.rb', line 136

def fetch(key, *default)
  if key.is_a?(Symbol)
    if headers.include? key
      col(key.to_sym)
    elsif default.any?
      default.first
    elsif block_given?
      yield key
    else
      raise IndexError, "row :#{key} does not exist"
    end
  else
    super
  end
end

#headersObject

Returns an array of column headers



153
154
155
# File 'lib/true_table.rb', line 153

def headers
  first.keys
end

#intersection(*others) ⇒ Object

Returns a new table with intersecting rows



158
159
160
# File 'lib/true_table.rb', line 158

def intersection(*others)
  self.class.new super
end

#join(row_separator = $,, col_separator = nil, with_headers: false) ⇒ Object

Returns a string with joined rows and columns



163
164
165
166
167
168
169
170
# File 'lib/true_table.rb', line 163

def join(row_separator = $,, col_separator = nil, with_headers: false)
  if col_separator
    result = map { |row| row.values.join col_separator }.join(row_separator)
    with_headers ? headers.join(col_separator) + row_separator + result : result
  else
    super row_separator
  end
end

#last(*args) ⇒ Object

Returns the last row or a new table with the last N rows



173
174
175
# File 'lib/true_table.rb', line 173

def last(*args)
  args.empty? ? super : self.class.new(super)
end

#rejectObject

Returns a new table without rejected rows



178
179
180
# File 'lib/true_table.rb', line 178

def reject
  self.class.new super
end

#reverseObject

Returns a reversed copy



183
184
185
# File 'lib/true_table.rb', line 183

def reverse
  self.class.new super
end

#rotate(count = 1) ⇒ Object

Returns a new table with the element at count as the first element



188
189
190
# File 'lib/true_table.rb', line 188

def rotate(count = 1)
  self.class.new super
end

#save_csv(path) ⇒ Object

Saves the table as a CSV file



196
197
198
# File 'lib/true_table.rb', line 196

def save_csv(path)
  File.write path, to_csv
end

#selectObject Also known as: filter

Returns a new table with selected rows



201
202
203
# File 'lib/true_table.rb', line 201

def select
  self.class.new super
end

#shuffle(*args) ⇒ Object

Returns a new shuffled tables



207
208
209
# File 'lib/true_table.rb', line 207

def shuffle(*args)
  self.class.new super
end

#slice(*args) ⇒ Object

Returns a new table slice



212
213
214
215
216
217
218
# File 'lib/true_table.rb', line 212

def slice(*args)
  if args.count == 1 and args.first.is_a? Integer
    super
  else
    self.class.new super
  end
end

#slice!(*args) ⇒ Object

Deletes and returns one more rows



221
222
223
224
225
226
227
# File 'lib/true_table.rb', line 221

def slice!(*args)
  if args.count == 1 and args.first.is_a? Integer
    super
  else
    self.class.new super
  end
end

#sortObject

Returns a new sorted table



230
231
232
# File 'lib/true_table.rb', line 230

def sort
  self.class.new super
end

#sort_byObject

Returns a new sorted table



235
236
237
# File 'lib/true_table.rb', line 235

def sort_by
  self.class.new super
end

#take(*args) ⇒ Object

Returns a new table with the first N rows



240
241
242
# File 'lib/true_table.rb', line 240

def take(*args)
  self.class.new super
end

#take_while(*args) ⇒ Object

Returns a new table with rows until the block returns false



245
246
247
# File 'lib/true_table.rb', line 245

def take_while(*args)
  self.class.new super
end

#to_csv(row_separator = "\n", col_separator = ",") ⇒ Object

Returns a CSV string



250
251
252
# File 'lib/true_table.rb', line 250

def to_csv(row_separator = "\n", col_separator = ",")
  join(row_separator, col_separator, with_headers: true)
end

#to_hObject

Returns a hash representation of the table using the values of the first column as hash keys



256
257
258
# File 'lib/true_table.rb', line 256

def to_h
  map { |row| [row.values.first, row] }.to_h
end

#valuesObject

Returns only values, without any headers (array of arrays)



261
262
263
# File 'lib/true_table.rb', line 261

def values
  map { |row| row.values }
end