github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/sortx/intersort.go (about) 1 package sortx 2 3 import ( 4 "fmt" 5 "reflect" 6 "sort" 7 ) 8 9 func less(x, y interface{}) bool { 10 justX := fmt.Sprint(map[interface{}]struct{}{x: {}}) 11 justY := fmt.Sprint(map[interface{}]struct{}{y: {}}) 12 return fmt.Sprint(map[interface{}]struct{}{ 13 x: {}, 14 y: {}, 15 }) == fmt.Sprintf("map[%v %v]", justX[4:len(justX)-1], justY[4:len(justY)-1]) 16 } 17 18 // Slice implements sort.Interface for arbitrary objects, according to the map ordering of the fmt package. 19 type Slice []interface{} 20 21 func (is Slice) Len() int { return len(is) } 22 func (is Slice) Swap(i, j int) { is[i], is[j] = is[j], is[i] } 23 func (is Slice) Less(i, j int) bool { return less(is[i], is[j]) } 24 25 type ( 26 Lesser func(a, b interface{}) bool 27 SortConfig struct { 28 Less Lesser 29 } 30 ) 31 32 type LessSlice struct { 33 Slice 34 Lesser 35 } 36 37 func WrapLesser(s Slice, lesser Lesser) LessSlice { 38 return LessSlice{Slice: s, Lesser: lesser} 39 } 40 41 func (is LessSlice) Less(i, j int) bool { return is.Lesser(is.Slice[i], is.Slice[j]) } 42 43 type SortOption func(*SortConfig) 44 45 func WithLess(f Lesser) SortOption { return func(c *SortConfig) { c.Less = f } } 46 47 // Sort sorts arbitrary objects according to the map ordering of the fmt package. 48 func Sort(slice interface{}, options ...SortOption) { 49 config := &SortConfig{} 50 for _, option := range options { 51 option(config) 52 } 53 if config.Less == nil { 54 config.Less = less 55 } 56 57 val := reflect.ValueOf(slice) 58 if val.Type().Kind() != reflect.Slice { 59 panic("sortx: cannot sort non-slice type") 60 } 61 sort.Slice(slice, func(i, j int) bool { 62 return config.Less(val.Index(i).Interface(), val.Index(j).Interface()) 63 }) 64 }