File: multiKeySort.go

package info (click to toggle)
golang-github-shenwei356-util 0.0~git20201231.861956c-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 192 kB
  • sloc: makefile: 2
file content (134 lines) | stat: -rw-r--r-- 2,773 bytes parent folder | download | duplicates (2)
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
package stringutil

import (
	"strconv"
	"strings"

	"github.com/shenwei356/natsort"
)

// SortType defines the sort type
type SortType struct {
	Index       int
	IgnoreCase  bool
	Natural     bool // natural order
	Number      bool
	UserDefined bool
	Reverse     bool
	Levels      map[string]int
}

// MultiKeyStringSlice sort [][]string by multiple keys
type MultiKeyStringSlice struct {
	SortTypes *[]SortType
	Value     []string
}

// MultiKeyStringSliceList is slice of MultiKeyStringSlice
type MultiKeyStringSliceList []MultiKeyStringSlice

func (list MultiKeyStringSliceList) Len() int { return len(list) }
func (list MultiKeyStringSliceList) Swap(i, j int) {
	list[i], list[j] = list[j], list[i]
}

func (list MultiKeyStringSliceList) Less(i, j int) bool {
	var err error
	var v int
	for _, t := range *list[i].SortTypes {
		if t.Natural {
			if t.IgnoreCase {
				v = strings.Compare(strings.ToLower(list[i].Value[t.Index]),
					strings.ToLower(list[j].Value[t.Index]))
			} else {
				v = strings.Compare(list[i].Value[t.Index], list[j].Value[t.Index])
			}
			if v == 0 {
				continue
			}

			if natsort.Compare(list[i].Value[t.Index], list[j].Value[t.Index], t.IgnoreCase) {
				v = -1
			} else {
				v = 1
			}
		} else if t.Number {
			var a, b float64
			a, err = strconv.ParseFloat(removeComma(list[i].Value[t.Index]), 64)
			if err != nil {
				a = 0
			}
			b, err = strconv.ParseFloat(removeComma(list[j].Value[t.Index]), 64)
			if err != nil {
				b = 0
			}
			if a < b {
				v = -1
			} else if a == b {
				v = 0
			} else {
				v = 1
			}
		} else if t.UserDefined {
			var a, b int
			var okA, okB bool
			if t.IgnoreCase {
				a, okA = t.Levels[strings.ToLower(list[i].Value[t.Index])]
				b, okB = t.Levels[strings.ToLower(list[j].Value[t.Index])]
			} else {
				a, okA = t.Levels[list[i].Value[t.Index]]
				b, okB = t.Levels[list[j].Value[t.Index]]
			}
			if okA {
				if okB {
					if a < b {
						v = -1
					} else if a == b {
						v = 0
					} else {
						v = 1
					}
				} else {
					v = -1
				}
			} else if okB {
				v = 1
			} else {
				v = strings.Compare(list[i].Value[t.Index], list[j].Value[t.Index])
			}
		} else {
			if t.IgnoreCase {
				v = strings.Compare(strings.ToLower(list[i].Value[t.Index]),
					strings.ToLower(list[j].Value[t.Index]))
			} else {
				v = strings.Compare(list[i].Value[t.Index], list[j].Value[t.Index])
			}
		}

		if v == 0 {
		} else if v < 0 {
			if t.Reverse {
				return false
			}
			return true
		} else {
			if t.Reverse {
				return true
			}
			return false
		}
	}
	return true
}

func removeComma(s string) string {
	newSlice := []byte{}
	for i := 0; i < len(s); i++ {
		switch s[i] {
		case ',':
		default:
			newSlice = append(newSlice, s[i])
		}
	}
	return string(newSlice)
}