-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcolumn.go
More file actions
141 lines (130 loc) · 5.09 KB
/
Copy pathcolumn.go
File metadata and controls
141 lines (130 loc) · 5.09 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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package simplecsv
// AddEmptyColumn adds an empty column at the end of the csv and returns a
// new csv. The original csv is not modified. columnName must not already
// exist as a header.
func (s SimpleCsv) AddEmptyColumn(columnName string) (SimpleCsv, bool) {
if len(s) == 0 || s.GetHeaderPosition(columnName) != -1 {
return s.fail()
}
newCsv := make(SimpleCsv, len(s))
for i, row := range s {
newRow := make([]string, len(row)+1)
copy(newRow, row)
if i == 0 {
newRow[len(row)] = columnName
}
newCsv[i] = newRow
}
return newCsv, true
}
// RemoveColumn removes the column in position X and returns a new csv.
// The original csv is not modified
func (s SimpleCsv) RemoveColumn(columnPosition int) (SimpleCsv, bool) {
if len(s) == 0 || columnPosition < 0 || columnPosition >= len(s[0]) {
return s.fail()
}
newCsv := make(SimpleCsv, len(s))
for i, row := range s {
if columnPosition < len(row) {
newRow := make([]string, 0, len(row)-1)
newRow = append(newRow, row[:columnPosition]...)
newRow = append(newRow, row[columnPosition+1:]...)
newCsv[i] = newRow
} else {
newCsv[i] = copyRow(row)
}
}
return newCsv, true
}
// RemoveColumnByName removes column by name
func (s SimpleCsv) RemoveColumnByName(columnName string) (SimpleCsv, bool) {
var removed bool
columnPosition := s.GetHeaderPosition(columnName)
s, removed = s.RemoveColumn(columnPosition)
return s, removed
}
// GetColumn returns a copy of the data cells of the column in position
// column, skipping the header cell in row 0. The caller can mutate the
// returned slice without affecting the csv. If the csv is empty or the
// column position is not valid, it returns an empty slice and false.
func (s SimpleCsv) GetColumn(column int) ([]string, bool) {
if len(s) == 0 || column < 0 || column >= len(s[0]) {
return []string{}, false
}
cells := make([]string, 0, len(s)-1)
for i := 1; i < len(s); i++ {
cells = append(cells, s[i][column])
}
return cells, true
}
// GetColumnByField returns a copy of the data cells of the column with the
// header name columnName, skipping the header cell in row 0. The caller can
// mutate the returned slice without affecting the csv. If the csv is empty
// or the field name does not exist, it returns an empty slice and false.
func (s SimpleCsv) GetColumnByField(columnName string) ([]string, bool) {
columnPosition := s.GetHeaderPosition(columnName)
if columnPosition == -1 || len(s) == 0 {
return []string{}, false
}
return s.GetColumn(columnPosition)
}
// SetColumn replaces the data cells of the column in position column with
// the values slice and returns a new csv. The header cell in row 0 is not
// modified and the original csv is not modified. len(values) must equal the
// number of data rows (len(s)-1), because every data row must keep exactly
// one cell in the column. The values are copied, changes to the original
// slice don't affect the csv. If the csv is empty, the column position is
// not valid or the length of values does not match, it returns a copy of
// the csv and false.
func (s SimpleCsv) SetColumn(column int, values []string) (SimpleCsv, bool) {
if len(s) == 0 || column < 0 || column >= len(s[0]) || len(values) != len(s)-1 {
return s.fail()
}
newCsv := copyRows(s)
for i, v := range values {
newCsv[i+1][column] = v
}
return newCsv, true
}
// SetColumnByField is SetColumn for the column with the header name
// columnName. If the csv is empty or the field name does not exist, it
// returns a copy of the csv and false.
func (s SimpleCsv) SetColumnByField(columnName string, values []string) (SimpleCsv, bool) {
columnPosition := s.GetHeaderPosition(columnName)
if columnPosition == -1 || len(s) == 0 {
return s.fail()
}
return s.SetColumn(columnPosition, values)
}
// MapColumnByField returns a new csv where every data cell of the column
// with the header name columnName is replaced by fn(value, row), called
// once per data row in csv order. row is the csv row index (1 for the
// first data row). The header cell in row 0 is not mapped and the original
// csv is not modified. If the csv is empty or the field name does not
// exist, it returns a copy of the csv and false.
func (s SimpleCsv) MapColumnByField(columnName string, fn func(value string, row int) string) (SimpleCsv, bool) {
columnPosition := s.GetHeaderPosition(columnName)
if columnPosition == -1 || len(s) == 0 {
return s.fail()
}
newCsv := copyRows(s)
for i := 1; i < len(s); i++ {
newCsv[i][columnPosition] = fn(newCsv[i][columnPosition], i)
}
return newCsv, true
}
// FillColumnByField returns a new csv where every data cell of the column
// with the header name columnName is set to value. The header cell in row 0
// is not modified and the original csv is not modified. If the csv is empty
// or the field name does not exist, it returns a copy of the csv and false.
func (s SimpleCsv) FillColumnByField(columnName string, value string) (SimpleCsv, bool) {
columnPosition := s.GetHeaderPosition(columnName)
if columnPosition == -1 || len(s) == 0 {
return s.fail()
}
newCsv := copyRows(s)
for i := 1; i < len(s); i++ {
newCsv[i][columnPosition] = value
}
return newCsv, true
}