Class: TrueTable

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

Constant Summary collapse

VERSION =
'0.2.3'

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

#-(other) ⇒ Object

Returns a new table without the specified columns



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

def -(other)
  keep_keys = headers - other
  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.has_value?(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
100
# 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



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

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

#dig(*indexes) ⇒ Object

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



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

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



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

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

#drop_while(*args) ⇒ Object

Returns a new table with rows until the block returns false



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

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

#each_colObject

Iterates over columns



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

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

#fetch(key, *default) ⇒ Object



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

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



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

def headers
  first.keys
end

#intersection(*others) ⇒ Object

Returns a new table with intersecting rows



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

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



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

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



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

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

#rejectObject

Returns a new table without rejected rows



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

def reject
  self.class.new super
end

#reverseObject

Returns a reversed copy



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

def reverse
  self.class.new super
end

#rotate(count = 1) ⇒ Object

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



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

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

#save_csv(path) ⇒ Object

Saves the table as a CSV file



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

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

#save_tsv(path) ⇒ Object

Saves the table as a TSV file



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

def save_tsv(path)
  File.write path, to_tsv
end

#selectObject Also known as: filter

Returns a new table with selected rows



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

def select
  self.class.new super
end

#shuffle(*args) ⇒ Object

Returns a new shuffled tables



213
214
215
# File 'lib/true_table.rb', line 213

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

#slice(*args) ⇒ Object

Returns a new table slice



218
219
220
221
222
223
224
# File 'lib/true_table.rb', line 218

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

#slice!(*args) ⇒ Object

Deletes and returns one more rows



227
228
229
230
231
232
233
# File 'lib/true_table.rb', line 227

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

#sortObject

Returns a new sorted table



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

def sort
  self.class.new super
end

#sort_byObject

Returns a new sorted table



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

def sort_by
  self.class.new super
end

#take(*args) ⇒ Object

Returns a new table with the first N rows



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

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

#take_while(*args) ⇒ Object

Returns a new table with rows until the block returns false



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

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

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

Returns a CSV string



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

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. If a block is given, the results of the block on each element of the array will be used as key => value pair.



268
269
270
271
272
273
274
# File 'lib/true_table.rb', line 268

def to_h
  if block_given?
    super
  else
    super { |row| [row.values.first, row] }
  end
end

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

Returns a TSV string



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

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

#valuesObject

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



277
278
279
# File 'lib/true_table.rb', line 277

def values
  map(&:values)
end