-
Notifications
You must be signed in to change notification settings - Fork 4
/
csv.go
92 lines (75 loc) · 1.64 KB
/
csv.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package csv
import (
"encoding/csv"
"io"
"strconv"
)
type ParseCSVOption func(*csv.Reader)
func WithComma(c rune) ParseCSVOption {
return func(r *csv.Reader) {
r.Comma = c
}
}
func WithComment(c rune) ParseCSVOption {
return func(r *csv.Reader) {
r.Comment = c
}
}
func WithLazyQuotes(l bool) ParseCSVOption {
return func(r *csv.Reader) {
r.LazyQuotes = l
}
}
func WithTrimLeadingSpace(t bool) ParseCSVOption {
return func(r *csv.Reader) {
r.TrimLeadingSpace = t
}
}
func WithFieldsPerRecord(f int) ParseCSVOption {
return func(r *csv.Reader) {
r.FieldsPerRecord = f
}
}
func ParseCSV(r io.Reader, options ...ParseCSVOption) (
[]string,
[]map[string]interface{},
error,
) {
csvReader := csv.NewReader(r)
for _, o := range options {
o(csvReader)
}
// Read the header row of the CSV file to use as keys for the maps
header, err := csvReader.Read()
if err != nil {
return nil, nil, err
}
var data []map[string]interface{}
for {
// Read each row of the CSV file
row, err := csvReader.Read()
if err == io.EOF {
break
}
if err != nil {
return nil, nil, err
}
// Create a new map to store the row data
rowData := make(map[string]interface{})
// Iterate over each column in the row and store the value in the map
for i, value := range row {
var v interface{}
v = value
// check if we can cast to int
if intV, err := strconv.Atoi(value); err == nil {
v = intV
} else if floatV, err := strconv.ParseFloat(value, 64); err == nil {
v = floatV
}
rowData[header[i]] = v
}
// Add the row data to the slice of maps
data = append(data, rowData)
}
return header, data, nil
}