Created
February 10, 2022 18:21
-
-
Save wcharczuk/094ffdfda02b4fb10961002ddd5ec8f2 to your computer and use it in GitHub Desktop.
Generic chained sorter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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