1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00

feat: add Sort function for slice

This commit is contained in:
dudaodong
2022-12-01 22:46:56 +08:00
parent d66f92cd68
commit ec27ad4c40
4 changed files with 77 additions and 1 deletions

View File

@@ -10,6 +10,8 @@ import (
"math/rand"
"reflect"
"sort"
"github.com/duke-git/lancet/v2/lancetconstraints"
)
// 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
}
// 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
// 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
func SortByField(slice any, field string, sortType ...string) error {
sv := sliceValue(slice)

View File

@@ -3,6 +3,8 @@ package slice
import (
"fmt"
"reflect"
"github.com/duke-git/lancet/v2/lancetconstraints"
)
// sliceValue return the reflect value of a slice
@@ -24,3 +26,40 @@ func sliceElemType(reflectType reflect.Type) reflect.Type {
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]
}

View File

@@ -538,6 +538,26 @@ func TestDifferenceBy(t *testing.T) {
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) {
assert := internal.NewAssert(t, "TestSortByFielDesc")