-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdistinct.go
More file actions
104 lines (98 loc) · 3.86 KB
/
Copy pathdistinct.go
File metadata and controls
104 lines (98 loc) · 3.86 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
package simplecsv
import (
"strconv"
"strings"
)
// Distinct returns the distinct values of the data cells of the column
// with the header name field, in order of first appearance. The header
// cell in row 0 is never included, and the returned slice is a copy:
// changes to it don't affect the csv. If the csv is empty or the field
// name does not exist, it returns an empty slice and false. A csv with
// only the header row returns an empty slice and true.
func (s SimpleCsv) Distinct(field string) ([]string, bool) {
columnPosition := s.GetHeaderPosition(field)
if columnPosition == -1 || len(s) == 0 {
return []string{}, false
}
seen := make(map[string]struct{})
values := make([]string, 0, len(s)-1)
for i := 1; i < len(s); i++ {
value := s[i][columnPosition]
if _, exists := seen[value]; exists {
continue
}
seen[value] = struct{}{}
values = append(values, value)
}
return values, true
}
// ValueCounts returns a new csv with the fixed headers value and count:
// one row per distinct value of the data cells of the column with the
// header name field, in order of first appearance, with the number of
// data rows that have that value as a decimal string. The header cell in
// row 0 is never counted. The original csv is not modified and the result
// shares no data with it. If the csv is empty or the field name does not
// exist, it returns a copy of the csv and false. A csv with only the
// header row yields a csv with just the value,count headers and true.
func (s SimpleCsv) ValueCounts(field string) (SimpleCsv, bool) {
columnPosition := s.GetHeaderPosition(field)
if columnPosition == -1 || len(s) == 0 {
return s.fail()
}
counts := make(map[string]int)
var order []string
for i := 1; i < len(s); i++ {
value := s[i][columnPosition]
if _, exists := counts[value]; !exists {
order = append(order, value)
}
counts[value]++
}
newCsv := make(SimpleCsv, 0, len(order)+1)
newCsv = append(newCsv, []string{"value", "count"})
for _, value := range order {
newCsv = append(newCsv, []string{value, strconv.FormatInt(int64(counts[value]), 10)})
}
return newCsv, true
}
// facetCount returns a map that counts how many times each string appears in
// the data cells of the column with the header name field. If caseSensitive
// is false, case does not matter: values that only differ in case are
// counted together under their lower-case key. If it is true, they are
// separate entries. The header cell in row 0 is never counted. It returns
// an empty map and false if the csv is empty, the field name is empty, or
// the field name does not exist. A csv with only the header row returns an
// empty map and true.
func (s SimpleCsv) facetCount(field string, caseSensitive bool) (map[string]int, bool) {
if field == "" {
return map[string]int{}, false
}
columnPosition := s.GetHeaderPosition(field)
if columnPosition == -1 {
return map[string]int{}, false
}
counts := make(map[string]int)
for i := 1; i < len(s); i++ {
value := s[i][columnPosition]
if !caseSensitive {
value = strings.ToLower(value)
}
counts[value]++
}
return counts, true
}
// FacetCount returns a map that counts how many times each string appears
// in the data cells of the column with the header name field. The header
// cell in row 0 is never counted. Case does not matter by default: Foo,
// foo and FOO are counted together under the lower-case key "foo". If the
// csv is empty, the field name is empty, or the field name does not exist,
// it returns an empty map and false. A csv with only the header row
// returns an empty map and true.
func (s SimpleCsv) FacetCount(field string) (map[string]int, bool) {
return s.facetCount(field, false)
}
// FacetCountCaseSensitive is like FacetCount but case matters: Foo, foo
// and FOO are counted as separate entries.
func (s SimpleCsv) FacetCountCaseSensitive(field string) (map[string]int, bool) {
return s.facetCount(field, true)
}