YouPlot/lib/youplot/dsv.rb

88 lines
2.2 KiB
Ruby
Raw Permalink Normal View History

2020-09-18 23:08:09 +08:00
# frozen_string_literal: true
2020-08-15 23:04:00 +08:00
require 'csv'
2020-11-23 12:09:16 +08:00
module YouPlot
2021-05-29 12:34:19 +08:00
# Module to handle DSV (Delimiter-separated values) format.
# Extract header and series.
2020-12-21 13:25:52 +08:00
module DSV
module_function
2020-11-25 16:34:50 +08:00
2020-12-21 15:09:37 +08:00
def parse(input, delimiter, headers, transpose)
2021-05-29 12:34:19 +08:00
# Parse as CSV
arr = CSV.parse(input, col_sep: delimiter)
# Remove blank lines
arr.delete_if do |i|
2021-06-03 09:48:47 +08:00
i == [] or i.all?(&:nil?)
2021-05-29 12:34:19 +08:00
end
# get header
headers = get_headers(arr, headers, transpose)
2021-05-29 12:34:19 +08:00
# get series
series = get_series(arr, headers, transpose)
2021-05-29 12:34:19 +08:00
# Return if No header
return Data.new(headers, series) if headers.nil?
# Warn if header contains nil
warn "\e[35mHeaders contains nil in it.\e[0m" if headers.include?(nil)
# Warn if header contains ''
warn "\e[35mHeaders contains \"\" in it.\e[0m" if headers.include? ''
# Make sure the number of elements in the header matches the number of series.
h_size = headers.size
s_size = series.size
if h_size > s_size
warn "\e[35mThe number of headers is greater than the number of series.\e[0m"
exit 1 if YouPlot.run_as_executable?
elsif h_size < s_size
warn "\e[35mThe number of headers is less than the number of series.\e[0m"
exit 1 if YouPlot.run_as_executable?
2020-08-19 22:47:28 +08:00
end
2021-05-29 12:34:19 +08:00
Data.new(headers, series) if h_size == s_size
end
# Transpose different sized ruby arrays
# https://stackoverflow.com/q/26016632
def transpose2(arr)
Array.new(arr.map(&:length).max) { |i| arr.map { |e| e[i] } }
end
def get_headers(arr, headers, transpose)
2021-05-29 12:34:19 +08:00
# header(-)
return nil unless headers
# header(+) trenspose(+)
return arr.map(&:first) if transpose
# header(+) transpose(-)
arr[0]
end
def get_series(arr, headers, transpose)
2021-05-29 12:34:19 +08:00
# header(-)
unless headers
return arr if transpose
return transpose2(arr)
end
2021-05-29 12:34:19 +08:00
# header(+) but no element in the series.
# TODO: should raise error?
return Array.new(arr[0].size, []) if arr.size == 1
# header(+) transpose(+)
return arr.map { |row| row[1..-1] } if transpose
# header(+) transpose(-)
transpose2(arr[1..-1])
end
end
end