-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathheader.go
More file actions
99 lines (92 loc) · 2.81 KB
/
Copy pathheader.go
File metadata and controls
99 lines (92 loc) · 2.81 KB
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
93
94
95
96
97
98
99
package simplecsv
// GetHeaders returns a copy of the headers as a slice
// If the csv is empty it returns an empty slice
func (s SimpleCsv) GetHeaders() []string {
if len(s) == 0 {
return []string{}
}
return copyRow(s[0])
}
// GetHeader returns the header name in a position
// Returns false as the second value if it does not exist
func (s SimpleCsv) GetHeader(columnPosition int) (string, bool) {
headers := s.GetHeaders()
if columnPosition >= 0 && columnPosition < len(headers) {
return headers[columnPosition], true
}
return "", false
}
// GetHeaderPosition returns the header position,
// returns -1 if it does not exist
func (s SimpleCsv) GetHeaderPosition(columnName string) int {
headers := s.GetHeaders()
for k, v := range headers {
if v == columnName {
return k
}
}
return -1
}
// headerIndex returns a map from header name to position, to avoid a linear
// scan per lookup. If a header name is duplicated, the first position wins,
// matching GetHeaderPosition
func (s SimpleCsv) headerIndex() map[string]int {
index := make(map[string]int)
if len(s) == 0 {
return index
}
for k, v := range s[0] {
if _, exists := index[v]; !exists {
index[v] = k
}
}
return index
}
// hasDuplicateHeaders reports whether headers contains the same name more than
// once. Empty headers are treated like any other name, so repeated empty
// strings count as duplicates. The library requires header names to be unique.
func hasDuplicateHeaders(headers []string) bool {
seen := make(map[string]struct{}, len(headers))
for _, h := range headers {
if _, exists := seen[h]; exists {
return true
}
seen[h] = struct{}{}
}
return false
}
// sameHeaders reports whether s and other have exactly the same header
// names in the same order. Empty csvs never have matching headers.
func (s SimpleCsv) sameHeaders(other SimpleCsv) bool {
if len(s) == 0 || len(other) == 0 {
return false
}
left, right := s[0], other[0]
if len(left) != len(right) {
return false
}
for i := range left {
if left[i] != right[i] {
return false
}
}
return true
}
// RenameHeader renames the header and returns a new csv
// Returns the second value as false if it did't found the oldHeader or if
// newHeader already exists as a different column: the library requires header
// names to be unique, so a rename that would produce a duplicate is rejected.
// Renaming a header to its own name is a no-op and is allowed.
// The original csv is not modified
func (s SimpleCsv) RenameHeader(oldHeader string, newHeader string) (SimpleCsv, bool) {
headerPosition := s.GetHeaderPosition(oldHeader)
if headerPosition < 0 || headerPosition >= len(s[0]) {
return s.fail()
}
if newHeader != oldHeader && s.GetHeaderPosition(newHeader) != -1 {
return s.fail()
}
newCsv := copyRows(s)
newCsv[0][headerPosition] = newHeader
return newCsv, true
}