Skip to content

Instantly share code, notes, and snippets.

@wcharczuk
Created February 10, 2022 18:21
Show Gist options
  • Save wcharczuk/094ffdfda02b4fb10961002ddd5ec8f2 to your computer and use it in GitHub Desktop.
Save wcharczuk/094ffdfda02b4fb10961002ddd5ec8f2 to your computer and use it in GitHub Desktop.
Generic chained sorter
package sortutil
import (
"constraints"
"sort"
)
// Sort sorts a list of elements by a given list of comparers.
func Sort[T any](elems []T, comparers ...SorterComparer[T]) {
if len(comparers) == 0 {
return
}
sort.Slice(elems, func(i, j int) bool {
var compare int
for _, sp := range comparers {
compare = sp.Compare(elems[i], elems[j])
if compare == 0 {
continue
}
return compare < 0
}
return false
})
}
// SortAsc is an identity sort ascending.
func SortAsc[T constraints.Ordered]() SorterComparer[T] {
return SorterComparerFunc[T](func(i, j T) int {
switch {
case i == j:
return 0
case i < j:
return -1
default:
return 1
}
})
}
// SortDesc is an identity sort descending.
func SortDesc[T constraints.Ordered]() SorterComparer[T] {
return SorterComparerFunc[T](func(i, j T) int {
switch {
case i == j:
return 0
case i > j:
return -1
default:
return 1
}
})
}
// SortKey is a sort comparer that extracts a key and sorts by it ascending.
func SortKey[T any, V constraints.Ordered](fn func(T) V) SorterComparer[T] {
return SorterComparerFunc[T](func(i, j T) int {
iv := fn(i)
jv := fn(j)
switch {
case iv == jv:
return 0
case iv < jv:
return -1
default:
return 1
}
})
}
// SortKeyDesc is a sort comparer that extracts a key and sorts by it descending.
func SortKeyDesc[T any, V constraints.Ordered](fn func(T) V) SorterComparer[T] {
return SorterComparerFunc[T](func(i, j T) int {
iv := fn(i)
jv := fn(j)
switch {
case iv == jv:
return 0
case iv > jv:
return -1
default:
return 1
}
})
}
// SorterComparer is a specific field or component of
// a multi-level sort.
type SorterComparer[T any] interface {
Compare(i, j T) int
}
// SorterComparer is a predicate for comparing two elements.
type SorterComparerFunc[T any] func(T, T) int
// Compare implements SorterComparer.
func (scf SorterComparerFunc[T]) Compare(i, j T) int {
return scf(i, j)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment