mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-12 08:42:29 +08:00
feat: add Sort function for slice
This commit is contained in:
@@ -16,3 +16,8 @@ type Comparator interface {
|
|||||||
type Number interface {
|
type Number interface {
|
||||||
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
|
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ordered is a constraint that permits any ordered type: any type that supports the operators < <= >= >
|
||||||
|
type Ordered interface {
|
||||||
|
Number | ~string
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/lancetconstraints"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Contain check if the target value is in the slice or not
|
// Contain check if the target value is in the slice or not
|
||||||
@@ -713,8 +715,18 @@ func Shuffle[T any](slice []T) []T {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort sorts a slice of any ordered type(number or string), use quick sort algrithm.
|
||||||
|
// default sort order is ascending (asc), if want descending order, set param `sortOrder` to `desc`
|
||||||
|
func Sort[T lancetconstraints.Ordered](slice []T, sortOrder ...string) {
|
||||||
|
if len(sortOrder) > 0 && sortOrder[0] == "desc" {
|
||||||
|
quickSort(slice, 0, len(slice)-1, "desc")
|
||||||
|
} else {
|
||||||
|
quickSort(slice, 0, len(slice)-1, "asc")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SortByField return sorted slice by field
|
// SortByField return sorted slice by field
|
||||||
// Slice element should be struct, field type should be int, uint, string, or bool
|
// slice element should be struct, field type should be int, uint, string, or bool
|
||||||
// default sortType is ascending (asc), if descending order, set sortType to desc
|
// default sortType is ascending (asc), if descending order, set sortType to desc
|
||||||
func SortByField(slice any, field string, sortType ...string) error {
|
func SortByField(slice any, field string, sortType ...string) error {
|
||||||
sv := sliceValue(slice)
|
sv := sliceValue(slice)
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package slice
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/lancetconstraints"
|
||||||
)
|
)
|
||||||
|
|
||||||
// sliceValue return the reflect value of a slice
|
// sliceValue return the reflect value of a slice
|
||||||
@@ -24,3 +26,40 @@ func sliceElemType(reflectType reflect.Type) reflect.Type {
|
|||||||
reflectType = reflectType.Elem()
|
reflectType = reflectType.Elem()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func quickSort[T lancetconstraints.Ordered](slice []T, lowIndex, highIndex int, order string) {
|
||||||
|
if lowIndex < highIndex {
|
||||||
|
p := partition(slice, lowIndex, highIndex, order)
|
||||||
|
quickSort(slice, lowIndex, p-1, order)
|
||||||
|
quickSort(slice, p+1, highIndex, order)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// partition split slice into two parts for quick sort
|
||||||
|
func partition[T lancetconstraints.Ordered](slice []T, lowIndex, highIndex int, order string) int {
|
||||||
|
p := slice[highIndex]
|
||||||
|
i := lowIndex
|
||||||
|
|
||||||
|
for j := lowIndex; j < highIndex; j++ {
|
||||||
|
if order == "desc" {
|
||||||
|
if slice[j] > p {
|
||||||
|
swap(slice, i, j)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if slice[j] < p {
|
||||||
|
swap(slice, i, j)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swap(slice, i, highIndex)
|
||||||
|
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
// swap two slice value at index i and j
|
||||||
|
func swap[T any](slice []T, i, j int) {
|
||||||
|
slice[i], slice[j] = slice[j], slice[i]
|
||||||
|
}
|
||||||
|
|||||||
@@ -538,6 +538,26 @@ func TestDifferenceBy(t *testing.T) {
|
|||||||
assert.Equal([]int{1, 2}, DifferenceBy(s1, s2, addOne))
|
assert.Equal([]int{1, 2}, DifferenceBy(s1, s2, addOne))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSort(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSort")
|
||||||
|
|
||||||
|
numbers := []int{1, 4, 3, 2, 5}
|
||||||
|
|
||||||
|
Sort(numbers)
|
||||||
|
assert.Equal([]int{1, 2, 3, 4, 5}, numbers)
|
||||||
|
|
||||||
|
Sort(numbers, "desc")
|
||||||
|
assert.Equal([]int{5, 4, 3, 2, 1}, numbers)
|
||||||
|
|
||||||
|
strings := []string{"a", "d", "c", "b", "e"}
|
||||||
|
|
||||||
|
Sort(strings)
|
||||||
|
assert.Equal([]string{"a", "b", "c", "d", "e"}, strings)
|
||||||
|
|
||||||
|
Sort(strings, "desc")
|
||||||
|
assert.Equal([]string{"e", "d", "c", "b", "a"}, strings)
|
||||||
|
}
|
||||||
|
|
||||||
func TestSortByFielDesc(t *testing.T) {
|
func TestSortByFielDesc(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestSortByFielDesc")
|
assert := internal.NewAssert(t, "TestSortByFielDesc")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user