Module compare
This commit is contained in:
parent
d85d270274
commit
58d52fa057
191 changed files with 49122 additions and 0 deletions
160
compare/compare.go
Normal file
160
compare/compare.go
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
package compare
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"gitea.zaclys.com/bvaudour/gob/unidecode"
|
||||
)
|
||||
|
||||
var (
|
||||
digit = regexp.MustCompile(`[^0-9]+|[0-9]+`)
|
||||
|
||||
ToLower = strings.ToLower
|
||||
ToAscii = unidecode.String
|
||||
)
|
||||
|
||||
func isNumber(input uint8) bool {
|
||||
return input >= '0' && input <= '9'
|
||||
}
|
||||
|
||||
// CompareFunc représente une fonction de comparaison de deux chaînes.
|
||||
type CompareFunc func(string, string) int
|
||||
|
||||
// TransformFunc représente une fonction de transformation de chaîne.
|
||||
type TransformFunc func(string) string
|
||||
|
||||
// BuildCompare retourne une fonction de comparaison à partir
|
||||
// d’un ensemble de comparaison à appliquer.
|
||||
func BuildCompare(cmps ...CompareFunc) CompareFunc {
|
||||
return func(e1, e2 string) int {
|
||||
for _, cmp := range cmps {
|
||||
if c := cmp(e1, e2); c != 0 {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// BuildTransform retourne une fonction de transformation à partir
|
||||
// de transformations successives.
|
||||
func BuildTransform(transforms ...TransformFunc) TransformFunc {
|
||||
return func(e string) string {
|
||||
for _, t := range transforms {
|
||||
e = t(e)
|
||||
}
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
func compareT(e1, e2 string, cb TransformFunc) int {
|
||||
return strings.Compare(cb(e1), cb(e2))
|
||||
}
|
||||
|
||||
// Compare compare deux chaînes après transformation.
|
||||
func Compare(e1, e2 string, t ...TransformFunc) int {
|
||||
return compareT(e1, e2, BuildTransform(t...))
|
||||
}
|
||||
|
||||
// CompareInsensitive compare deux chaîne sans tenir compte de la casse.
|
||||
func CompareInsensitive(e1, e2 string) int {
|
||||
return Compare(e1, e2, ToLower)
|
||||
}
|
||||
|
||||
// CompareAscii compare deux chaînes sans tenir compte des accents.
|
||||
func CompareAscii(e1, e2 string) int {
|
||||
return Compare(e1, e2, ToAscii)
|
||||
}
|
||||
|
||||
// CompareAscii compare deux chaînes sans tenir compte des accents ni de la casse.
|
||||
func CompareAsciiInsensitive(e1, e2 string) int {
|
||||
return Compare(e1, e2, ToAscii, ToLower)
|
||||
}
|
||||
|
||||
func naturalT(e1, e2 string, cb TransformFunc) int {
|
||||
e1, e2 = cb(e1), cb(e2)
|
||||
sl1 := digit.FindAllString(strings.Replace(e1, " ", "", -1), -1)
|
||||
sl2 := digit.FindAllString(strings.Replace(e2, " ", "", -1), -1)
|
||||
|
||||
l := len(sl1)
|
||||
if len(sl2) < l {
|
||||
l = len(sl2)
|
||||
}
|
||||
for i, s1 := range sl1[:l] {
|
||||
s2 := sl2[i]
|
||||
// Both parts are equal
|
||||
if s1 == s2 {
|
||||
continue
|
||||
}
|
||||
n1, n2 := isNumber(s1[0]), isNumber(s2[0])
|
||||
switch {
|
||||
case n1 && n2:
|
||||
s1 = strings.TrimLeft(s1, "0")
|
||||
s2 = strings.TrimLeft(s2, "0")
|
||||
return Compare(s1, s2)
|
||||
case n1:
|
||||
return -1
|
||||
case n2:
|
||||
return 1
|
||||
}
|
||||
return Compare(s1, s2)
|
||||
}
|
||||
|
||||
l = len(e1)
|
||||
if len(e2) < len(e1) {
|
||||
l = len(e2)
|
||||
}
|
||||
// Fall back for cases where space characters have been annihliated by the replacment call
|
||||
// Here we iterate over the unmolsested string and prioritize numbers over
|
||||
for i, b1 := range []byte(e1[:l]) {
|
||||
b2 := e2[i]
|
||||
switch {
|
||||
case isNumber(b1):
|
||||
return -1
|
||||
case isNumber(b2):
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return Compare(e1, e2)
|
||||
}
|
||||
|
||||
// Natural compare des chaînes de façon “naturelle” (ie. en analysant
|
||||
// les nombres éventuels compris dans la chaîne).
|
||||
func Natural(e1, e2 string, t ...TransformFunc) int {
|
||||
return naturalT(e1, e2, BuildTransform(t...))
|
||||
}
|
||||
|
||||
// NaturalInsensitive compare des chaînes de manière naturelle sans tenir
|
||||
// compte de la casse.
|
||||
func NaturalInsensitive(e1, e2 string) int {
|
||||
return Natural(e1, e2, ToLower)
|
||||
}
|
||||
|
||||
// NaturalAscii compare des chaînes de manière naturelle sans tenir
|
||||
// compte des accents.
|
||||
func NaturalAscii(e1, e2 string) int {
|
||||
return Natural(e1, e2, ToAscii)
|
||||
}
|
||||
|
||||
// NaturalAsciiInsensitive compare des chaînes de manière naturelle sans tenir
|
||||
// compte de la casse ni des accents.
|
||||
func NaturalAsciiInsensitive(e1, e2 string) int {
|
||||
return Natural(e1, e2, ToAscii, ToLower)
|
||||
}
|
||||
|
||||
// Less transforme une succession de fonctions de comparaison
|
||||
// en <.
|
||||
func Less(cmps ...CompareFunc) func(string, string) bool {
|
||||
return func(e1, e2 string) bool {
|
||||
return BuildCompare(cmps...)(e1, e2) < 0
|
||||
}
|
||||
}
|
||||
|
||||
// Equal transforme une succession de fonctions de comparaison
|
||||
// en =.
|
||||
func Equal(cmps ...CompareFunc) func(string, string) bool {
|
||||
return func(e1, e2 string) bool {
|
||||
return BuildCompare(cmps...)(e1, e2) == 0
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue