...
1 package table
2
3 import (
4 "sort"
5 "strconv"
6 )
7
8
9 type SortBy struct {
10
11
12
13 Name string
14
15
16 Number int
17
18
19 Mode SortMode
20 }
21
22
23 type SortMode int
24
25 const (
26
27 Asc SortMode = iota
28
29 AscNumeric
30
31 Dsc
32
33 DscNumeric
34 )
35
36 type rowsSorter struct {
37 rows []rowStr
38 sortBy []SortBy
39 sortedIndices []int
40 }
41
42
43
44 func (t *Table) getSortedRowIndices() []int {
45 sortedIndices := make([]int, len(t.rows))
46 for idx := range t.rows {
47 sortedIndices[idx] = idx
48 }
49
50 if t.sortBy != nil && len(t.sortBy) > 0 {
51 sort.Sort(rowsSorter{
52 rows: t.rows,
53 sortBy: t.parseSortBy(t.sortBy),
54 sortedIndices: sortedIndices,
55 })
56 }
57
58 return sortedIndices
59 }
60
61 func (t *Table) parseSortBy(sortBy []SortBy) []SortBy {
62 var resSortBy []SortBy
63 for _, col := range sortBy {
64 colNum := 0
65 if col.Number > 0 && col.Number <= t.numColumns {
66 colNum = col.Number
67 } else if col.Name != "" && len(t.rowsHeader) > 0 {
68 for idx, colName := range t.rowsHeader[0] {
69 if col.Name == colName {
70 colNum = idx + 1
71 break
72 }
73 }
74 }
75 if colNum > 0 {
76 resSortBy = append(resSortBy, SortBy{
77 Name: col.Name,
78 Number: colNum,
79 Mode: col.Mode,
80 })
81 }
82 }
83 return resSortBy
84 }
85
86 func (rs rowsSorter) Len() int {
87 return len(rs.rows)
88 }
89
90 func (rs rowsSorter) Swap(i, j int) {
91 rs.sortedIndices[i], rs.sortedIndices[j] = rs.sortedIndices[j], rs.sortedIndices[i]
92 }
93
94 func (rs rowsSorter) Less(i, j int) bool {
95 realI, realJ := rs.sortedIndices[i], rs.sortedIndices[j]
96 for _, col := range rs.sortBy {
97 rowI, rowJ, colIdx := rs.rows[realI], rs.rows[realJ], col.Number-1
98 if colIdx < len(rowI) && colIdx < len(rowJ) {
99 shouldContinue, returnValue := rs.lessColumns(rowI, rowJ, colIdx, col)
100 if !shouldContinue {
101 return returnValue
102 }
103 }
104 }
105 return false
106 }
107
108 func (rs rowsSorter) lessColumns(rowI rowStr, rowJ rowStr, colIdx int, col SortBy) (bool, bool) {
109 if rowI[colIdx] == rowJ[colIdx] {
110 return true, false
111 } else if col.Mode == Asc {
112 return false, rowI[colIdx] < rowJ[colIdx]
113 } else if col.Mode == Dsc {
114 return false, rowI[colIdx] > rowJ[colIdx]
115 }
116
117 iVal, iErr := strconv.ParseFloat(rowI[colIdx], 64)
118 jVal, jErr := strconv.ParseFloat(rowJ[colIdx], 64)
119 if iErr == nil && jErr == nil {
120 if col.Mode == AscNumeric {
121 return false, iVal < jVal
122 } else if col.Mode == DscNumeric {
123 return false, jVal < iVal
124 }
125 }
126 return true, false
127 }
128
View as plain text