Class: CalcProfit::Table
- Inherits:
-
Object
- Object
- CalcProfit::Table
- Defined in:
- lib/calc_profit/table.rb
Overview
A container for a two-dimensional table that can be used as input of a set of transactions and output for results of calculations. All cells in the table are kept as strings with no attempt to determine their type. The table is maintained as an array of hashes accessible from the Table#rows method.
Initialize a new table with the name of a .csv file or a .org file. The initializer will populate the table with the first csv or org table structure found in either file. You can also pass in an IO object for either type of file, but in that case, you need to specify ‘.csv’ or ‘.ext’ as the second argument to tell it what kind of file format to expect. Finally, the constructor will also take an array of arrays or an array of hashes. In the former case, if the second array’s first element is a string that looks like a rule spearator, ‘———–’, ‘+———-’, etc., the headers will be taken from the first array. In the latter case, the keys of the hashes will be used as headers. It is assumed that all the hashes have the same keys.
In the resulting array of hashes, the headers are converted into symbols, with all spaces converted to underscore and everything down-cased. So, the heading, ‘Two Words’ becomes the hash key :two_words.
Instance Attribute Summary collapse
-
#rows ⇒ Object
readonly
Returns the value of attribute rows.
Instance Method Summary collapse
- #<<(row) ⇒ Object
- #column_sum(col) ⇒ Object
- #headers ⇒ Object
-
#initialize(input = nil, ext = '.csv') ⇒ Table
constructor
A new instance of Table.
- #read_table_from_array_of_arrays(rows) ⇒ Object
- #read_table_from_array_of_hashes(rows) ⇒ Object
- #read_table_from_csv(io) ⇒ Object
-
#read_table_from_org(io) ⇒ Object
Form rows of table by reading the first table found in the org file.
Constructor Details
#initialize(input = nil, ext = '.csv') ⇒ Table
Returns a new instance of Table.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/calc_profit/table.rb', line 28 def initialize(input = nil, ext = '.csv') case input when NilClass @rows = [] when IO, StringIO case ext when '.csv' @rows = read_table_from_csv(input) when '.org' @rows = read_table_from_org(input) else raise "Don't know how to read a #{ext} file." end when String ext = File.extname(input).downcase File.open(input, 'r') do |io| case ext when '.csv' @rows = read_table_from_csv(io) when '.org' @rows = read_table_from_org(io) else raise "Don't know how to read a #{ext} file." end end when Array case input[0] when Array @rows = read_table_from_array_of_arrays(input) when Hash @rows = read_table_from_array_of_hashes(input) else raise ArgumentError, "Table object initialized with unknown data type" end else raise ArgumentError, "Table object initialized with unknown data type" end end |
Instance Attribute Details
#rows ⇒ Object (readonly)
Returns the value of attribute rows.
26 27 28 |
# File 'lib/calc_profit/table.rb', line 26 def rows @rows end |
Instance Method Details
#<<(row) ⇒ Object
67 68 69 |
# File 'lib/calc_profit/table.rb', line 67 def <<(row) @rows << row end |
#column_sum(col) ⇒ Object
147 148 149 |
# File 'lib/calc_profit/table.rb', line 147 def column_sum(col) rows.map{ |r| r[col].gsub(/[,$]/, '').to_f }.inject(:+) end |
#headers ⇒ Object
143 144 145 |
# File 'lib/calc_profit/table.rb', line 143 def headers rows[0].keys end |
#read_table_from_array_of_arrays(rows) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/calc_profit/table.rb', line 104 def read_table_from_array_of_arrays(rows) hrule_re = /\A\s*[-+]+\s*\z/ headers = [] first_data_row = 0 if rows[1][0] =~ hrule_re # Use first row as headers headers = rows[0].map(&:as_sym) first_data_row = 2 else headers = (1..rows[0].size).to_a.map{|k| "col#{k}".as_sym } end hash_rows = [] rows[first_data_row..-1].each do |row| row = row.map{ |s| s.to_s.strip } hash_rows << Hash[headers.zip(row)] end hash_rows end |
#read_table_from_array_of_hashes(rows) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/calc_profit/table.rb', line 123 def read_table_from_array_of_hashes(rows) hash_rows = [] rows.each do |row| hash = {} row.each_pair do |k, v| case k when String key = k.as_sym when Symbol key = k else key = k.to_s.as_sym end hash[key] = v.to_s.strip end hash_rows << hash end hash_rows end |
#read_table_from_csv(io) ⇒ Object
71 72 73 74 75 76 77 78 |
# File 'lib/calc_profit/table.rb', line 71 def read_table_from_csv(io) rows = [] ::CSV.new(io, headers: true, header_converters: :symbol, skip_blanks: true).each do |row| rows << row.to_hash end rows end |
#read_table_from_org(io) ⇒ Object
Form rows of table by reading the first table found in the org file.
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/calc_profit/table.rb', line 81 def read_table_from_org(io) # For determining when we're looking at lines of the table, after # the table with name /table_name/ has been spotted. table_re = /\A\s*\|/ rows = [] table_found = false io.each do |line| if !table_found # Skip through the file until a table is found if line =~ table_re table_found = true else next end end break unless line =~ table_re line = line.sub(/\A\s*\|/, '').sub(/\|\s*\z/, '') rows << line.split('|') end read_table_from_array_of_arrays(rows) end |