1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-15 02:02:27 +08:00

Compare commits

...

3 Commits

Author SHA1 Message Date
dudaodong
f8b785c4cb doc: add doc for Sort and SortBy 2022-12-02 15:47:16 +08:00
dudaodong
82c8a04c35 make SortByField function deprecate 2022-12-02 15:17:08 +08:00
dudaodong
280ecb5cef feat: add SortBy function for slice 2022-12-02 14:53:57 +08:00
5 changed files with 247 additions and 7 deletions

View File

@@ -59,7 +59,9 @@ import (
- [ReplaceAll](#ReplaceAll)
- [Repeat](#Repeat)
- [Shuffle](#Shuffle)
- [SortByField](#SortByField)
- [Sort](#Sort)
- [SortBy](#SortBy)
- [SortByField<sup>Deprecated</sup>](#SortByField)
- [Some](#Some)
- [StringSlice](#StringSlice)
- [SymmetricDifference](#SymmetricDifference)
@@ -1099,7 +1101,94 @@ func main() {
}
```
### <span id="SortByField">SortByField</span>
### <span id="Sort">Sort</span>
<p>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`. Ordered type: number(all ints uints floats) or string.
</p>
<b>Signature:</b>
```go
func Sort[T lancetconstraints.Ordered](slice []T, sortOrder ...string)
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
numbers := []int{1, 4, 3, 2, 5}
slice.Sort(numbers)
fmt.Println(numbers) //{1,2,3,4,5}
slice.Sort(numbers, "desc")
fmt.Println(numbers) //{5,4,3,2,1}
strings := []string{"a", "d", "c", "b", "e"}
slice.Sort(strings)
fmt.Println(strings) //{"a", "b", "c", "d", "e"}
slice.Sort(strings, "desc")
fmt.Println(strings) //{"e", "d", "c", "b", "a"}
}
```
### <span id="SortBy">SortBy</span>
<p>Sorts the slice in ascending order as determined by the less function. This sort is not guaranteed to be stable.<p>
<b>Signature:</b>
```go
func SortBy[T any](slice []T, less func(a, b T) bool)
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
numbers := []int{1, 4, 3, 2, 5}
slice.SortBy(numbers, func(a, b int) bool {
return a < b
})
fmt.Println(numbers) //{1, 2, 3, 4, 5}
type User struct {
Name string
Age uint
}
users := []User{
{Name: "a", Age: 21},
{Name: "b", Age: 15},
{Name: "c", Age: 100}}
slice.SortBy(users, func(a, b User) bool {
return a.Age < b.Age
})
fmt.Printf("sort users by age: %v", users)
// output
// [{b 15} {a 21} {c 100}]
}
```
### <span id="SortByField">SortByField (Deprecated: use Sort and SortBy for replacement)</span>
<p>Sort struct slice by field. Slice element should be struct, field type should be int, uint, string, or bool. Default sort type is ascending (asc), if descending order, set sortType to desc</p>

View File

@@ -61,7 +61,9 @@ import (
- [ReplaceAll](#ReplaceAll)
- [Repeat](#Repeat)
- [Shuffle](#Shuffle)
- [SortByField](#SortByField)
- [Sort](#Sort)
- [SortBy](#SortBy)
- [SortByField<sup>Deprecated</sup>](#SortByField)
- [Some](#Some)
- [StringSlice](#StringSlice)
- [SymmetricDifference](#SymmetricDifference)
@@ -1099,7 +1101,93 @@ func main() {
}
```
### <span id="SortByField">SortByField</span>
### <span id="Sort">Sort</span>
<p>对任何有序类型(数字或字符串)的切片进行排序,使用快速排序算法。 默认排序顺序为升序 (asc),如果需要降序,请将参数 `sortOrder` 设置为 `desc`。 Ordered类型数字所有整数浮点数或字符串。</p>
<b>函数签名:</b>
```go
func Sort[T lancetconstraints.Ordered](slice []T, sortOrder ...string)
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
numbers := []int{1, 4, 3, 2, 5}
slice.Sort(numbers)
fmt.Println(numbers) //{1,2,3,4,5}
slice.Sort(numbers, "desc")
fmt.Println(numbers) //{5,4,3,2,1}
strings := []string{"a", "d", "c", "b", "e"}
slice.Sort(strings)
fmt.Println(strings) //{"a", "b", "c", "d", "e"}
slice.Sort(strings, "desc")
fmt.Println(strings) //{"e", "d", "c", "b", "a"}
}
```
### <span id="SortBy">SortBy</span>
<p>按照less函数确定的升序规则对切片进行排序。排序不保证稳定性</p>
<b>函数签名:</b>
```go
func SortBy[T any](slice []T, less func(a, b T) bool)
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
numbers := []int{1, 4, 3, 2, 5}
slice.SortBy(numbers, func(a, b int) bool {
return a < b
})
fmt.Println(numbers) //{1, 2, 3, 4, 5}
type User struct {
Name string
Age uint
}
users := []User{
{Name: "a", Age: 21},
{Name: "b", Age: 15},
{Name: "c", Age: 100}}
slice.SortBy(users, func(a, b User) bool {
return a.Age < b.Age
})
fmt.Printf("sort users by age: %v", users)
// output
// [{b 15} {a 21} {c 100}]
}
```
### <span id="SortByField">SortByField (已弃用: 请使用 Sort或SortBy 代替该方法)</span>
<p>按字段对结构切片进行排序。slice元素应为struct字段类型应为int、uint、string或bool。 默认排序类型是升序asc如果是降序设置 sortType 为 desc</p>

View File

@@ -725,9 +725,16 @@ func Sort[T lancetconstraints.Ordered](slice []T, sortOrder ...string) {
}
}
// SortBy sorts the slice in ascending order as determined by the less function.
// This sort is not guaranteed to be stable
func SortBy[T any](slice []T, less func(a, b T) bool) {
quickSortBy(slice, 0, len(slice)-1, less)
}
// SortByField return sorted slice by field
// 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
// This function is deprecated, use Sort and SortBy for replacement
func SortByField(slice any, field string, sortType ...string) error {
sv := sliceValue(slice)
t := sv.Type().Elem()

View File

@@ -29,14 +29,14 @@ func sliceElemType(reflectType reflect.Type) reflect.Type {
func quickSort[T lancetconstraints.Ordered](slice []T, lowIndex, highIndex int, order string) {
if lowIndex < highIndex {
p := partition(slice, lowIndex, highIndex, order)
p := partitionOrderedSlice(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 {
// partitionOrderedSlice split ordered slice into two parts for quick sort
func partitionOrderedSlice[T lancetconstraints.Ordered](slice []T, lowIndex, highIndex int, order string) int {
p := slice[highIndex]
i := lowIndex
@@ -59,6 +59,32 @@ func partition[T lancetconstraints.Ordered](slice []T, lowIndex, highIndex int,
return i
}
func quickSortBy[T any](slice []T, lowIndex, highIndex int, less func(a, b T) bool) {
if lowIndex < highIndex {
p := partitionAnySlice(slice, lowIndex, highIndex, less)
quickSortBy(slice, lowIndex, p-1, less)
quickSortBy(slice, p+1, highIndex, less)
}
}
// partitionAnySlice split any slice into two parts for quick sort
func partitionAnySlice[T any](slice []T, lowIndex, highIndex int, less func(a, b T) bool) int {
p := slice[highIndex]
i := lowIndex
for j := lowIndex; j < highIndex; j++ {
if less(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

@@ -558,6 +558,36 @@ func TestSort(t *testing.T) {
assert.Equal([]string{"e", "d", "c", "b", "a"}, strings)
}
func TestSortBy(t *testing.T) {
assert := internal.NewAssert(t, "TestSortBy")
numbers := []int{1, 4, 3, 2, 5}
SortBy(numbers, func(a, b int) bool {
return a < b
})
assert.Equal([]int{1, 2, 3, 4, 5}, numbers)
type User struct {
Name string
Age uint
}
users := []User{
{Name: "a", Age: 21},
{Name: "b", Age: 15},
{Name: "c", Age: 100}}
SortBy(users, func(a, b User) bool {
return a.Age < b.Age
})
t.Logf("sort users by age: %v", users)
// output
// [{b 15} {a 21} {c 100}]
}
func TestSortByFielDesc(t *testing.T) {
assert := internal.NewAssert(t, "TestSortByFielDesc")