forked from MagicalTux/natsort
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnatsort.go
112 lines (100 loc) · 1.84 KB
/
natsort.go
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
// Package natsort implements natural strings sorting
package natsort
import (
"sort"
"strings"
)
type stringSlice []string
func (s stringSlice) Len() int {
return len(s)
}
func (s stringSlice) Less(a, b int) bool {
return Compare(s[a], s[b])
}
func (s stringSlice) Swap(a, b int) {
s[a], s[b] = s[b], s[a]
}
// Sort sorts a list of strings in a natural order
func Sort(l []string) {
sort.Sort(stringSlice(l))
}
// Compare returns true if the first string precedes the second one according to natural order
func Compare(a, b string) bool {
lnA := len(a)
lnB := len(b)
posA := 0
posB := 0
for {
if lnA <= posA {
if lnB <= posB {
// eof on both at the same time (equal)
return false
}
return true
} else if lnB <= posB {
// eof on b
return false
}
av, bv := a[posA], b[posB]
if av >= '0' && av <= '9' && bv >= '0' && bv <= '9' {
// go into numeric mode
intLnA := 1
intLnB := 1
for {
if posA+intLnA >= lnA {
break
}
x := a[posA+intLnA]
if av == '0' {
posA += 1
av = x
continue
}
if x >= '0' && x <= '9' {
intLnA += 1
} else {
break
}
}
for {
if posB+intLnB >= lnB {
break
}
x := b[posB+intLnB]
if bv == '0' {
posB += 1
bv = x
continue
}
if x >= '0' && x <= '9' {
intLnB += 1
} else {
break
}
}
if intLnB > intLnA {
// length of a value is longer, means it's a bigger number
return true
} else if intLnA > intLnB {
return false
}
// both have same length, let's compare as string
v := strings.Compare(a[posA:posA+intLnA], b[posB:posB+intLnB])
if v < 0 {
return true
} else if v > 0 {
return false
}
// equal
posA += intLnA
posB += intLnB
continue
}
if av == bv {
posA += 1
posB += 1
continue
}
return av < bv
}
}