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  }