github.com/puellanivis/breton@v0.2.16/lib/sort/sort.go (about)

     1  // Package sort provides sorting implementations for all builtin data-types and an implementation of Radix sort.
     2  package sort // import "github.com/puellanivis/breton/lib/sort"
     3  
     4  import (
     5  	"sort"
     6  )
     7  
     8  // Interface is just a wrapper around the the built in sort.Interface
     9  type Interface interface {
    10  	sort.Interface
    11  }
    12  
    13  // Sort attempts a radix sort of the argument, otherwise, it tries to sort.Sort.
    14  func Sort(a interface{}) {
    15  	Radix(a)
    16  }
    17  
    18  // Stable runs sort.Stable on the given argument.
    19  //
    20  // If the argument it is a basic slice type, it is wrapped through this packages implementations.
    21  // If the argument is a sort.Interface, then it is called directly.
    22  func Stable(a interface{}) {
    23  	if a == nil {
    24  		return
    25  	}
    26  
    27  	switch a := a.(type) {
    28  	case []uint:
    29  		sort.Stable(UintSlice(a))
    30  	case []uint8:
    31  		sort.Stable(Uint8Slice(a))
    32  	case []uint16:
    33  		sort.Stable(Uint16Slice(a))
    34  	case []uint32:
    35  		sort.Stable(Uint32Slice(a))
    36  	case []uint64:
    37  		sort.Stable(Uint64Slice(a))
    38  
    39  	case []int:
    40  		sort.Stable(IntSlice(a))
    41  	case []int8:
    42  		sort.Stable(Int8Slice(a))
    43  	case []int16:
    44  		sort.Stable(Int16Slice(a))
    45  	case []int32:
    46  		sort.Stable(Int32Slice(a))
    47  	case []int64:
    48  		sort.Stable(Int64Slice(a))
    49  
    50  	case []float32:
    51  		sort.Stable(Float32Slice(a))
    52  	case []float64:
    53  		sort.Stable(Float64Slice(a))
    54  
    55  	case []string:
    56  		sort.Stable(StringSlice(a))
    57  	case [][]byte:
    58  		sort.Stable(ByteSliceSlice(a))
    59  	case [][]rune:
    60  		sort.Stable(RuneSliceSlice(a))
    61  
    62  	default:
    63  		// fallback: use the builtin sort
    64  		sort.Stable(a.(sort.Interface))
    65  	}
    66  }
    67  
    68  // we need to wrap these two together to cover all of the operations that need be reversed into one interface.
    69  type reversable interface {
    70  	RadixInterface
    71  	Comparer
    72  }
    73  
    74  // now that the functions are all wrapped up together, we can use a single anonymous interface to wrap this.
    75  type reverse struct {
    76  	reversable
    77  }
    78  
    79  func (a reverse) Less(i, j int) bool {
    80  	return !a.reversable.Less(i, j)
    81  }
    82  
    83  func (a reverse) Compare(i, j int) int {
    84  	return -a.reversable.Compare(i, j)
    85  }
    86  
    87  func (a reverse) CompareFunc(x interface{}) func(int) int {
    88  	f := a.reversable.CompareFunc(x)
    89  
    90  	return func(i int) int { return -f(i) }
    91  }
    92  
    93  func (a reverse) RadixFunc(r int) RadixTest {
    94  	f := a.reversable.RadixFunc(r)
    95  
    96  	return func(i int) bool {
    97  		return !f(i)
    98  	}
    99  }
   100  
   101  // Reverse performs a reverse sort of a given argument, according to the conditions noted for Sort.
   102  func Reverse(a interface{}) sort.Interface {
   103  	if a == nil {
   104  		return sort.Reverse(sort.Interface(nil))
   105  	}
   106  
   107  	switch a := a.(type) {
   108  	case reversable:
   109  		return &reverse{a}
   110  
   111  	case []uint:
   112  		return &reverse{UintSlice(a)}
   113  	case []uint8:
   114  		return &reverse{Uint8Slice(a)}
   115  	case []uint16:
   116  		return &reverse{Uint16Slice(a)}
   117  	case []uint32:
   118  		return &reverse{Uint32Slice(a)}
   119  	case []uint64:
   120  		return &reverse{Uint64Slice(a)}
   121  
   122  	case []int:
   123  		return &reverse{IntSlice(a)}
   124  	case []int8:
   125  		return &reverse{Int8Slice(a)}
   126  	case []int16:
   127  		return &reverse{Int16Slice(a)}
   128  	case []int32:
   129  		return &reverse{Int32Slice(a)}
   130  	case []int64:
   131  		return &reverse{Int64Slice(a)}
   132  
   133  	case []float32:
   134  		return &reverse{Float32Slice(a)}
   135  	case []float64:
   136  		return &reverse{Float64Slice(a)}
   137  
   138  	case []string:
   139  		return &reverse{StringSlice(a)}
   140  	case [][]byte:
   141  		return &reverse{ByteSliceSlice(a)}
   142  	case [][]rune:
   143  		return &reverse{RuneSliceSlice(a)}
   144  	}
   145  
   146  	return sort.Reverse(a.(sort.Interface))
   147  }
   148  
   149  // IsSorted returns true if the given argument is in sorted order.
   150  func IsSorted(a interface{}) bool {
   151  	if a == nil {
   152  		return true
   153  	}
   154  
   155  	switch a := a.(type) {
   156  	case []uint:
   157  		return sort.IsSorted(UintSlice(a))
   158  	case []uint8:
   159  		return sort.IsSorted(Uint8Slice(a))
   160  	case []uint16:
   161  		return sort.IsSorted(Uint16Slice(a))
   162  	case []uint32:
   163  		return sort.IsSorted(Uint32Slice(a))
   164  	case []uint64:
   165  		return sort.IsSorted(Uint64Slice(a))
   166  
   167  	case []int:
   168  		return sort.IsSorted(IntSlice(a))
   169  	case []int8:
   170  		return sort.IsSorted(Int8Slice(a))
   171  	case []int16:
   172  		return sort.IsSorted(Int16Slice(a))
   173  	case []int32:
   174  		return sort.IsSorted(Int32Slice(a))
   175  	case []int64:
   176  		return sort.IsSorted(Int64Slice(a))
   177  
   178  	case []float32:
   179  		return sort.IsSorted(Float32Slice(a))
   180  	case []float64:
   181  		return sort.IsSorted(Float64Slice(a))
   182  
   183  	case []string:
   184  		return sort.IsSorted(StringSlice(a))
   185  	case [][]byte:
   186  		return sort.IsSorted(ByteSliceSlice(a))
   187  	case [][]rune:
   188  		return sort.IsSorted(RuneSliceSlice(a))
   189  	}
   190  
   191  	return sort.IsSorted(a.(sort.Interface))
   192  }