mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-23 13:52:26 +08:00
Compare commits
16 Commits
v2.1.14
...
888381a06c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
888381a06c | ||
|
|
a554eb7ef4 | ||
|
|
26ff90122b | ||
|
|
75b27c6540 | ||
|
|
a7e77fa98d | ||
|
|
abf392117a | ||
|
|
d231d9f572 | ||
|
|
97447d058e | ||
|
|
040e112aa6 | ||
|
|
afb021b4b5 | ||
|
|
5075774000 | ||
|
|
6bba44dc50 | ||
|
|
422022c74d | ||
|
|
87fcf97e2d | ||
|
|
05d1f348d4 | ||
|
|
6f2f1f3004 |
16
README.md
16
README.md
@@ -832,9 +832,15 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>DeleteAt</big>** : delete the element of slice from specific start index to end index - 1.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteAt)]
|
||||
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
|
||||
- **<big>Drop</big>** : creates a slice with `n` elements dropped from the beginning when n > 0, or `n` elements dropped from the ending when n < 0.
|
||||
- **<big>Drop</big>** : drop n elements from the start of a slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)]
|
||||
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
|
||||
- **<big>DropRight</big>** : drop n elements from the end of a slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DropRight)]
|
||||
- **<big>DropWhile</big>** : drop n elements from the start of a slice while predicate function returns true.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DropWhile)]
|
||||
- **<big>DropRightWhile</big>** : drop n elements from the end of a slice while predicate function returns true.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DropRightWhile)]
|
||||
- **<big>Equal</big>** : checks if two slices are equal: the same length and all elements' order and value are equal.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Equal)]
|
||||
[[play](https://go.dev/play/p/WcRQJ37ifPa)]
|
||||
@@ -910,6 +916,14 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>Shuffle</big>** : shuffle the slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Shuffle)]
|
||||
[[play](https://go.dev/play/p/YHvhnWGU3Ge)]
|
||||
- **<big>IsAscending</big>** : Checks if a slice is ascending order.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsAscending)]
|
||||
- **<big>IsDescending</big>** : Checks if a slice is descending order.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsDescending)]
|
||||
- **<big>IsSorted</big>** : Checks if a slice is sorted (ascending or descending).
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsSorted)]
|
||||
- **<big>IsSortedByKey</big>** : Checks if a slice is sorted by iteratee function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsSortedByKey)]
|
||||
- **<big>Sort</big>** : sorts a slice of any ordered type(number or string).
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Sort)]
|
||||
[[play](https://go.dev/play/p/V9AVjzf_4Fk)]
|
||||
|
||||
@@ -839,9 +839,15 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>DeleteAt</big>** : 删除切片中指定开始索引到结束索引的元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteAt)]
|
||||
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
|
||||
- **<big>Drop</big>** : 创建一个切片,当n > 0时从开头删除n个元素,或者当n < 0时从结尾删除n个元素。
|
||||
- **<big>Drop</big>** : 从切片头部删除n个元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Drop)]
|
||||
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
|
||||
- **<big>DropRight</big>** : 从切片尾部删除n个元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DropRight)]
|
||||
- **<big>DropWhile</big>** : 从切片的头部删除n个元素,这个n个元素满足predicate函数返回true。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DropWhile)]
|
||||
- **<big>DropRightWhile</big>** : 从切片的尾部删除n个元素,这个n个元素满足predicate函数返回true。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DropRightWhile)]
|
||||
- **<big>Equal</big>** : 检查两个切片是否相等,相等条件:切片长度相同,元素顺序和值都相同。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Equal)]
|
||||
[[play](https://go.dev/play/p/WcRQJ37ifPa)]
|
||||
@@ -917,6 +923,14 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>Shuffle</big>** : 随机打乱切片中的元素顺序。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Shuffle)]
|
||||
[[play](https://go.dev/play/p/YHvhnWGU3Ge)]
|
||||
- **<big>IsAscending</big>** : 检查切片元素是否按升序排列。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsAscending)]
|
||||
- **<big>IsDescending</big>** : 检查切片元素是否按降序排列。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsDescending)]
|
||||
- **<big>IsSorted</big>** : 检查切片元素是否是有序的(升序或降序)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsSorted)]
|
||||
- **<big>IsSortedByKey</big>** : 通过iteratee函数,检查切片元素是否是有序的。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsSortedByKey)]
|
||||
- **<big>Sort</big>** : 对任何有序类型(数字或字符串)的切片进行排序,使用快速排序算法。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Sort)]
|
||||
[[play](https://go.dev/play/p/V9AVjzf_4Fk)]
|
||||
|
||||
294
docs/slice.md
294
docs/slice.md
@@ -35,6 +35,9 @@ import (
|
||||
- [DifferenceWith](#DifferenceWith)
|
||||
- [DeleteAt](#DeleteAt)
|
||||
- [Drop](#Drop)
|
||||
- [DropRight](#DropRight)
|
||||
- [DropWhile](#DropWhile)
|
||||
- [DropRightWhile](#DropRightWhile)
|
||||
- [Equal](#Equal)
|
||||
- [EqualWith](#EqualWith)
|
||||
- [Every](#Every)
|
||||
@@ -60,6 +63,10 @@ import (
|
||||
- [ReplaceAll](#ReplaceAll)
|
||||
- [Repeat](#Repeat)
|
||||
- [Shuffle](#Shuffle)
|
||||
- [IsAscending](#IsAscending)
|
||||
- [IsDescending](#IsDescending)
|
||||
- [IsSorted](#IsSorted)
|
||||
- [IsSortedByKey](#IsSortedByKey)
|
||||
- [Sort](#Sort)
|
||||
- [SortBy](#SortBy)
|
||||
- [SortByField<sup>deprecated</sup>](#SortByField)
|
||||
@@ -487,7 +494,7 @@ func main() {
|
||||
|
||||
### <span id="Drop">Drop</span>
|
||||
|
||||
<p>Creates a slice with `n` elements dropped from the beginning when n > 0, or `n` elements dropped from the ending when n < 0.</p>
|
||||
<p>Drop n elements from the start of a slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -505,20 +512,139 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := slice.Drop([]string{"a", "b", "c"}, 0)
|
||||
result2 := slice.Drop([]string{"a", "b", "c"}, 1)
|
||||
result3 := slice.Drop([]string{"a", "b", "c"}, -1)
|
||||
result4 := slice.Drop([]string{"a", "b", "c"}, 4)
|
||||
result2 := slice.Drop([]string{"a", "b", "c"}, 1)
|
||||
result3 := slice.Drop([]string{"a", "b", "c"}, -1)
|
||||
result4 := slice.Drop([]string{"a", "b", "c"}, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// [a b c]
|
||||
// [b c]
|
||||
// [a b]
|
||||
// []
|
||||
// Output:
|
||||
// [a b c]
|
||||
// [b c]
|
||||
// [a b c]
|
||||
// []
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DropRight">DropRight</span>
|
||||
|
||||
<p>Drop n elements from the end of a slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func DropRight[T any](slice []T, n int) []T
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.DropRight([]string{"a", "b", "c"}, 0)
|
||||
result2 := slice.DropRight([]string{"a", "b", "c"}, 1)
|
||||
result3 := slice.DropRight([]string{"a", "b", "c"}, -1)
|
||||
result4 := slice.DropRight([]string{"a", "b", "c"}, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// [a b c]
|
||||
// [a b]
|
||||
// [a b c]
|
||||
// []
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DropWhile">DropWhile</span>
|
||||
|
||||
<p>Drop n elements from the start of a slice while predicate function returns true.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func DropWhile[T any](slice []T, predicate func(item T) bool) []T
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.DropWhile(numbers, func(n int) bool {
|
||||
return n != 2
|
||||
})
|
||||
result2 := slice.DropWhile(numbers, func(n int) bool {
|
||||
return true
|
||||
})
|
||||
result3 := slice.DropWhile(numbers, func(n int) bool {
|
||||
return n == 0
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// [2 3 4 5]
|
||||
// []
|
||||
// [1 2 3 4 5]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DropRightWhile">DropRightWhile</span>
|
||||
|
||||
<p>Drop n elements from the end of a slice while predicate function returns true.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func DropRightWhile[T any](slice []T, predicate func(item T) bool) []T
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
numbers := []int{1, 2, 3, 4, 5}
|
||||
|
||||
result1 := slice.DropRightWhile(numbers, func(n int) bool {
|
||||
return n != 2
|
||||
})
|
||||
result2 := slice.DropRightWhile(numbers, func(n int) bool {
|
||||
return true
|
||||
})
|
||||
result3 := slice.DropRightWhile(numbers, func(n int) bool {
|
||||
return n == 0
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// [1 2]
|
||||
// []
|
||||
// [1 2 3 4 5]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1348,6 +1474,148 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsAscending">IsAscending</span>
|
||||
|
||||
<p>Checks if a slice is ascending order.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsAscending[T constraints.Ordered](slice []T) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.IsAscending([]int{1, 2, 3, 4, 5})
|
||||
result2 := slice.IsAscending([]int{5, 4, 3, 2, 1})
|
||||
result3 := slice.IsAscending([]int{2, 1, 3, 4, 5})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsDescending">IsDescending</span>
|
||||
|
||||
<p>Checks if a slice is descending order.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsDescending[T constraints.Ordered](slice []T) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.IsDescending([]int{5, 4, 3, 2, 1})
|
||||
result2 := slice.IsDescending([]int{1, 2, 3, 4, 5})
|
||||
result3 := slice.IsDescending([]int{2, 1, 3, 4, 5})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsSorted">IsSorted</span>
|
||||
|
||||
<p>Checks if a slice is sorted (ascending or descending).</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsSorted[T constraints.Ordered](slice []T) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.IsSorted([]int{5, 4, 3, 2, 1})
|
||||
result2 := slice.IsSorted([]int{1, 2, 3, 4, 5})
|
||||
result3 := slice.IsSorted([]int{2, 1, 3, 4, 5})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsSortedByKey">IsSortedByKey</span>
|
||||
|
||||
<p>Checks if a slice is sorted by iteratee function.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsSortedByKey[T any, K constraints.Ordered](slice []T, iteratee func(item T) K) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.IsSortedByKey([]string{"a", "ab", "abc"}, func(s string) int {
|
||||
return len(s)
|
||||
})
|
||||
result2 := slice.IsSortedByKey([]string{"abc", "ab", "a"}, func(s string) int {
|
||||
return len(s)
|
||||
})
|
||||
result3 := slice.IsSortedByKey([]string{"abc", "a", "ab"}, func(s string) int {
|
||||
return len(s)
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <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.
|
||||
|
||||
@@ -35,6 +35,9 @@ import (
|
||||
- [DifferenceWith](#DifferenceWith)
|
||||
- [DeleteAt](#DeleteAt)
|
||||
- [Drop](#Drop)
|
||||
- [DropRight](#DropRight)
|
||||
- [DropWhile](#DropWhile)
|
||||
- [DropRightWhile](#DropRightWhile)
|
||||
- [Every](#Every)
|
||||
- [Equal](#Equal)
|
||||
- [EqualWith](#EqualWith)
|
||||
@@ -60,6 +63,10 @@ import (
|
||||
- [ReplaceAll](#ReplaceAll)
|
||||
- [Repeat](#Repeat)
|
||||
- [Shuffle](#Shuffle)
|
||||
- [IsAscending](#IsAscending)
|
||||
- [IsDescending](#IsDescending)
|
||||
- [IsSorted](#IsSorted)
|
||||
- [IsSortedByKey](#IsSortedByKey)
|
||||
- [Sort](#Sort)
|
||||
- [SortBy](#SortBy)
|
||||
- [SortByField<sup>deprecated</sup>](#SortByField)
|
||||
@@ -486,9 +493,10 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Drop">Drop</span>
|
||||
|
||||
<p>创建一个切片,当n > 0时从开头删除n个元素,或者当n < 0时从结尾删除n个元素</p>
|
||||
<p>从切片的头部删除n个元素。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -506,20 +514,139 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := slice.Drop([]string{"a", "b", "c"}, 0)
|
||||
result2 := slice.Drop([]string{"a", "b", "c"}, 1)
|
||||
result3 := slice.Drop([]string{"a", "b", "c"}, -1)
|
||||
result4 := slice.Drop([]string{"a", "b", "c"}, 4)
|
||||
result2 := slice.Drop([]string{"a", "b", "c"}, 1)
|
||||
result3 := slice.Drop([]string{"a", "b", "c"}, -1)
|
||||
result4 := slice.Drop([]string{"a", "b", "c"}, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// [a b c]
|
||||
// [b c]
|
||||
// [a b]
|
||||
// []
|
||||
// Output:
|
||||
// [a b c]
|
||||
// [b c]
|
||||
// [a b c]
|
||||
// []
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DropRight">DropRight</span>
|
||||
|
||||
<p>从切片的尾部删除n个元素。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func DropRight[T any](slice []T, n int) []T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.DropRight([]string{"a", "b", "c"}, 0)
|
||||
result2 := slice.DropRight([]string{"a", "b", "c"}, 1)
|
||||
result3 := slice.DropRight([]string{"a", "b", "c"}, -1)
|
||||
result4 := slice.DropRight([]string{"a", "b", "c"}, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// [a b c]
|
||||
// [a b]
|
||||
// [a b c]
|
||||
// []
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DropWhile">DropWhile</span>
|
||||
|
||||
<p>从切片的头部删除n个元素,这个n个元素满足predicate函数返回true。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func DropWhile[T any](slice []T, predicate func(item T) bool) []T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.DropWhile(numbers, func(n int) bool {
|
||||
return n != 2
|
||||
})
|
||||
result2 := slice.DropWhile(numbers, func(n int) bool {
|
||||
return true
|
||||
})
|
||||
result3 := slice.DropWhile(numbers, func(n int) bool {
|
||||
return n == 0
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// [2 3 4 5]
|
||||
// []
|
||||
// [1 2 3 4 5]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DropRightWhile">DropRightWhile</span>
|
||||
|
||||
<p>从切片的尾部删除n个元素,这个n个元素满足predicate函数返回true。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func DropRightWhile[T any](slice []T, predicate func(item T) bool) []T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
numbers := []int{1, 2, 3, 4, 5}
|
||||
|
||||
result1 := slice.DropRightWhile(numbers, func(n int) bool {
|
||||
return n != 2
|
||||
})
|
||||
result2 := slice.DropRightWhile(numbers, func(n int) bool {
|
||||
return true
|
||||
})
|
||||
result3 := slice.DropRightWhile(numbers, func(n int) bool {
|
||||
return n == 0
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// [1 2]
|
||||
// []
|
||||
// [1 2 3 4 5]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1349,6 +1476,148 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsAscending">IsAscending</span>
|
||||
|
||||
<p>检查切片元素是否按升序排列。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsAscending[T constraints.Ordered](slice []T) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.IsAscending([]int{1, 2, 3, 4, 5})
|
||||
result2 := slice.IsAscending([]int{5, 4, 3, 2, 1})
|
||||
result3 := slice.IsAscending([]int{2, 1, 3, 4, 5})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsDescending">IsDescending</span>
|
||||
|
||||
<p>检查切片元素是否按降序排列。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsDescending[T constraints.Ordered](slice []T) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.IsDescending([]int{5, 4, 3, 2, 1})
|
||||
result2 := slice.IsDescending([]int{1, 2, 3, 4, 5})
|
||||
result3 := slice.IsDescending([]int{2, 1, 3, 4, 5})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsSorted">IsSorted</span>
|
||||
|
||||
<p>检查切片元素是否是有序的(升序或降序)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsSorted[T constraints.Ordered](slice []T) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.IsSorted([]int{5, 4, 3, 2, 1})
|
||||
result2 := slice.IsSorted([]int{1, 2, 3, 4, 5})
|
||||
result3 := slice.IsSorted([]int{2, 1, 3, 4, 5})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsSortedByKey">IsSortedByKey</span>
|
||||
|
||||
<p>通过iteratee函数,检查切片元素是否是有序的。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsSortedByKey[T any, K constraints.Ordered](slice []T, iteratee func(item T) K) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.IsSortedByKey([]string{"a", "ab", "abc"}, func(s string) int {
|
||||
return len(s)
|
||||
})
|
||||
result2 := slice.IsSortedByKey([]string{"abc", "ab", "a"}, func(s string) int {
|
||||
return len(s)
|
||||
})
|
||||
result3 := slice.IsSortedByKey([]string{"abc", "a", "ab"}, func(s string) int {
|
||||
return len(s)
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sort">Sort</span>
|
||||
|
||||
<p>对任何有序类型(数字或字符串)的切片进行排序,使用快速排序算法。 默认排序顺序为升序 (asc),如果需要降序,请将参数 `sortOrder` 设置为 `desc`。 Ordered类型:数字(所有整数浮点数)或字符串。</p>
|
||||
|
||||
@@ -13,10 +13,10 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
NUMERAL = "0123456789"
|
||||
LOWER_LETTERS = "abcdefghijklmnopqrstuvwxyz"
|
||||
UPPER_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
Numeral = "0123456789"
|
||||
LowwerLetters = "abcdefghijklmnopqrstuvwxyz"
|
||||
UpperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
Letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
)
|
||||
|
||||
// RandInt generate random int between min and max, maybe min, not be max.
|
||||
@@ -51,31 +51,31 @@ func RandBytes(length int) []byte {
|
||||
// RandString generate random string of specified length.
|
||||
// Play: https://go.dev/play/p/W2xvRUXA7Mi
|
||||
func RandString(length int) string {
|
||||
return random(LETTERS, length)
|
||||
return random(Letters, length)
|
||||
}
|
||||
|
||||
// RandUpper generate a random upper case string.
|
||||
// Play: https://go.dev/play/p/29QfOh0DVuh
|
||||
func RandUpper(length int) string {
|
||||
return random(UPPER_LETTERS, length)
|
||||
return random(UpperLetters, length)
|
||||
}
|
||||
|
||||
// RandLower generate a random lower case string.
|
||||
// Play: https://go.dev/play/p/XJtZ471cmtI
|
||||
func RandLower(length int) string {
|
||||
return random(LOWER_LETTERS, length)
|
||||
return random(LowwerLetters, length)
|
||||
}
|
||||
|
||||
// RandNumeral generate a random numeral string of specified length.
|
||||
// Play: https://go.dev/play/p/g4JWVpHsJcf
|
||||
func RandNumeral(length int) string {
|
||||
return random(NUMERAL, length)
|
||||
return random(Numeral, length)
|
||||
}
|
||||
|
||||
// RandNumeralOrLetter generate a random numeral or letter string.
|
||||
// Play: https://go.dev/play/p/19CEQvpx2jD
|
||||
func RandNumeralOrLetter(length int) string {
|
||||
return random(NUMERAL+LETTERS, length)
|
||||
return random(Numeral+Letters, length)
|
||||
}
|
||||
|
||||
// random generate a random string based on given string range.
|
||||
|
||||
125
slice/slice.go
125
slice/slice.go
@@ -6,7 +6,6 @@ package slice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"sort"
|
||||
@@ -559,24 +558,72 @@ func DeleteAt[T any](slice []T, start int, end ...int) []T {
|
||||
return slice
|
||||
}
|
||||
|
||||
// Drop creates a slice with `n` elements dropped from the beginning when n > 0, or `n` elements dropped from the ending when n < 0.
|
||||
// Drop drop n elements from the start of a slice.
|
||||
// Play: https://go.dev/play/p/pJ-d6MUWcvK
|
||||
func Drop[T any](slice []T, n int) []T {
|
||||
size := len(slice)
|
||||
|
||||
if size == 0 || n == 0 {
|
||||
return slice
|
||||
}
|
||||
|
||||
if math.Abs(float64(n)) >= float64(size) {
|
||||
if size <= n {
|
||||
return []T{}
|
||||
}
|
||||
|
||||
if n < 0 {
|
||||
return slice[0 : size+n]
|
||||
if n <= 0 {
|
||||
return slice
|
||||
}
|
||||
|
||||
return slice[n:size]
|
||||
result := make([]T, 0, size-n)
|
||||
|
||||
return append(result, slice[n:]...)
|
||||
}
|
||||
|
||||
// DropRight drop n elements from the end of a slice.
|
||||
// Play: todo
|
||||
func DropRight[T any](slice []T, n int) []T {
|
||||
size := len(slice)
|
||||
|
||||
if size <= n {
|
||||
return []T{}
|
||||
}
|
||||
|
||||
if n <= 0 {
|
||||
return slice
|
||||
}
|
||||
|
||||
result := make([]T, 0, size-n)
|
||||
|
||||
return append(result, slice[:size-n]...)
|
||||
}
|
||||
|
||||
// DropWhile drop n elements from the start of a slice while predicate function returns true.
|
||||
// Play: todo
|
||||
func DropWhile[T any](slice []T, predicate func(item T) bool) []T {
|
||||
i := 0
|
||||
|
||||
for ; i < len(slice); i++ {
|
||||
if !predicate(slice[i]) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
result := make([]T, 0, len(slice)-i)
|
||||
|
||||
return append(result, slice[i:]...)
|
||||
}
|
||||
|
||||
// DropRightWhile drop n elements from the end of a slice while predicate function returns true.
|
||||
// Play: todo
|
||||
func DropRightWhile[T any](slice []T, predicate func(item T) bool) []T {
|
||||
i := len(slice) - 1
|
||||
|
||||
for ; i >= 0; i-- {
|
||||
if !predicate(slice[i]) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
result := make([]T, 0, i+1)
|
||||
|
||||
return append(result, slice[:i+1]...)
|
||||
}
|
||||
|
||||
// InsertAt insert the value or other slice into slice at index.
|
||||
@@ -783,6 +830,64 @@ func Shuffle[T any](slice []T) []T {
|
||||
return slice
|
||||
}
|
||||
|
||||
// IsAscending checks if a slice is ascending order.
|
||||
// Play: todo
|
||||
func IsAscending[T constraints.Ordered](slice []T) bool {
|
||||
for i := 1; i < len(slice); i++ {
|
||||
if slice[i-1] > slice[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// IsDescending checks if a slice is descending order.
|
||||
// Play: todo
|
||||
func IsDescending[T constraints.Ordered](slice []T) bool {
|
||||
for i := 1; i < len(slice); i++ {
|
||||
if slice[i-1] < slice[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// IsSorted checks if a slice is sorted(ascending or descending).
|
||||
// Play: todo
|
||||
func IsSorted[T constraints.Ordered](slice []T) bool {
|
||||
return IsAscending(slice) || IsDescending(slice)
|
||||
}
|
||||
|
||||
// IsSortedByKey checks if a slice is sorted by iteratee function.
|
||||
// Play: todo
|
||||
func IsSortedByKey[T any, K constraints.Ordered](slice []T, iteratee func(item T) K) bool {
|
||||
size := len(slice)
|
||||
|
||||
isAscending := func(data []T) bool {
|
||||
for i := 0; i < size-1; i++ {
|
||||
if iteratee(data[i]) > iteratee(data[i+1]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
isDescending := func(data []T) bool {
|
||||
for i := 0; i < size-1; i++ {
|
||||
if iteratee(data[i]) < iteratee(data[i+1]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return isAscending(slice) || isDescending(slice)
|
||||
}
|
||||
|
||||
// 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`.
|
||||
// Play: https://go.dev/play/p/V9AVjzf_4Fk
|
||||
|
||||
@@ -482,10 +482,74 @@ func ExampleDrop() {
|
||||
// Output:
|
||||
// [a b c]
|
||||
// [b c]
|
||||
// [a b]
|
||||
// [a b c]
|
||||
// []
|
||||
}
|
||||
|
||||
func ExampleDropRight() {
|
||||
result1 := DropRight([]string{"a", "b", "c"}, 0)
|
||||
result2 := DropRight([]string{"a", "b", "c"}, 1)
|
||||
result3 := DropRight([]string{"a", "b", "c"}, -1)
|
||||
result4 := DropRight([]string{"a", "b", "c"}, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// [a b c]
|
||||
// [a b]
|
||||
// [a b c]
|
||||
// []
|
||||
}
|
||||
|
||||
func ExampleDropWhile() {
|
||||
numbers := []int{1, 2, 3, 4, 5}
|
||||
|
||||
result1 := DropWhile(numbers, func(n int) bool {
|
||||
return n != 2
|
||||
})
|
||||
result2 := DropWhile(numbers, func(n int) bool {
|
||||
return true
|
||||
})
|
||||
result3 := DropWhile(numbers, func(n int) bool {
|
||||
return n == 0
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// [2 3 4 5]
|
||||
// []
|
||||
// [1 2 3 4 5]
|
||||
}
|
||||
|
||||
func ExampleDropRightWhile() {
|
||||
numbers := []int{1, 2, 3, 4, 5}
|
||||
|
||||
result1 := DropRightWhile(numbers, func(n int) bool {
|
||||
return n != 2
|
||||
})
|
||||
result2 := DropRightWhile(numbers, func(n int) bool {
|
||||
return true
|
||||
})
|
||||
result3 := DropRightWhile(numbers, func(n int) bool {
|
||||
return n == 0
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// [1 2]
|
||||
// []
|
||||
// [1 2 3 4 5]
|
||||
}
|
||||
|
||||
func ExampleInsertAt() {
|
||||
result1 := InsertAt([]string{"a", "b", "c"}, 0, "1")
|
||||
result2 := InsertAt([]string{"a", "b", "c"}, 1, "1")
|
||||
@@ -621,6 +685,75 @@ func ExampleReverse() {
|
||||
// [d c b a]
|
||||
}
|
||||
|
||||
func ExampleIsAscending() {
|
||||
|
||||
result1 := IsAscending([]int{1, 2, 3, 4, 5})
|
||||
result2 := IsAscending([]int{5, 4, 3, 2, 1})
|
||||
result3 := IsAscending([]int{2, 1, 3, 4, 5})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleIsDescending() {
|
||||
|
||||
result1 := IsDescending([]int{5, 4, 3, 2, 1})
|
||||
result2 := IsDescending([]int{1, 2, 3, 4, 5})
|
||||
result3 := IsDescending([]int{2, 1, 3, 4, 5})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleIsSorted() {
|
||||
|
||||
result1 := IsSorted([]int{1, 2, 3, 4, 5})
|
||||
result2 := IsSorted([]int{5, 4, 3, 2, 1})
|
||||
result3 := IsSorted([]int{2, 1, 3, 4, 5})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleIsSortedByKey() {
|
||||
result1 := IsSortedByKey([]string{"a", "ab", "abc"}, func(s string) int {
|
||||
return len(s)
|
||||
})
|
||||
result2 := IsSortedByKey([]string{"abc", "ab", "a"}, func(s string) int {
|
||||
return len(s)
|
||||
})
|
||||
result3 := IsSortedByKey([]string{"abc", "a", "ab"}, func(s string) int {
|
||||
return len(s)
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleSort() {
|
||||
nums := []int{1, 4, 3, 2, 5}
|
||||
|
||||
|
||||
@@ -377,7 +377,7 @@ func TestDeleteAt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDrop(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestInterfaceSlice")
|
||||
assert := internal.NewAssert(t, "TestDrop")
|
||||
|
||||
assert.Equal([]int{}, Drop([]int{}, 0))
|
||||
assert.Equal([]int{}, Drop([]int{}, 1))
|
||||
@@ -388,9 +388,64 @@ func TestDrop(t *testing.T) {
|
||||
assert.Equal([]int{}, Drop([]int{1, 2, 3, 4, 5}, 5))
|
||||
assert.Equal([]int{}, Drop([]int{1, 2, 3, 4, 5}, 6))
|
||||
|
||||
assert.Equal([]int{1, 2, 3, 4}, Drop([]int{1, 2, 3, 4, 5}, -1))
|
||||
assert.Equal([]int{}, Drop([]int{1, 2, 3, 4, 5}, -6))
|
||||
assert.Equal([]int{}, Drop([]int{1, 2, 3, 4, 5}, -6))
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, Drop([]int{1, 2, 3, 4, 5}, -1))
|
||||
}
|
||||
|
||||
func TestDropRight(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDropRight")
|
||||
|
||||
assert.Equal([]int{}, DropRight([]int{}, 0))
|
||||
assert.Equal([]int{}, DropRight([]int{}, 1))
|
||||
assert.Equal([]int{}, DropRight([]int{}, -1))
|
||||
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, DropRight([]int{1, 2, 3, 4, 5}, 0))
|
||||
assert.Equal([]int{1, 2, 3, 4}, DropRight([]int{1, 2, 3, 4, 5}, 1))
|
||||
assert.Equal([]int{}, DropRight([]int{1, 2, 3, 4, 5}, 5))
|
||||
assert.Equal([]int{}, DropRight([]int{1, 2, 3, 4, 5}, 6))
|
||||
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, DropRight([]int{1, 2, 3, 4, 5}, -1))
|
||||
}
|
||||
|
||||
func TestDropWhile(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDropWhile")
|
||||
|
||||
numbers := []int{1, 2, 3, 4, 5}
|
||||
|
||||
r1 := DropWhile(numbers, func(n int) bool {
|
||||
return n != 2
|
||||
})
|
||||
assert.Equal([]int{2, 3, 4, 5}, r1)
|
||||
|
||||
r2 := DropWhile(numbers, func(n int) bool {
|
||||
return true
|
||||
})
|
||||
assert.Equal([]int{}, r2)
|
||||
|
||||
r3 := DropWhile(numbers, func(n int) bool {
|
||||
return n == 0
|
||||
})
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, r3)
|
||||
}
|
||||
|
||||
func TestDropRightWhile(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDropRightWhile")
|
||||
|
||||
numbers := []int{1, 2, 3, 4, 5}
|
||||
|
||||
r1 := DropRightWhile(numbers, func(n int) bool {
|
||||
return n != 2
|
||||
})
|
||||
assert.Equal([]int{1, 2}, r1)
|
||||
|
||||
r2 := DropRightWhile(numbers, func(n int) bool {
|
||||
return true
|
||||
})
|
||||
assert.Equal([]int{}, r2)
|
||||
|
||||
r3 := DropRightWhile(numbers, func(n int) bool {
|
||||
return n == 0
|
||||
})
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, r3)
|
||||
}
|
||||
|
||||
func TestInsertAt(t *testing.T) {
|
||||
@@ -548,6 +603,46 @@ func TestDifferenceBy(t *testing.T) {
|
||||
assert.Equal([]int{1, 2}, DifferenceBy(s1, s2, addOne))
|
||||
}
|
||||
|
||||
func TestIsAscending(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsAscending")
|
||||
|
||||
assert.Equal(true, IsAscending([]int{1, 2, 3, 4, 5}))
|
||||
assert.Equal(false, IsAscending([]int{5, 4, 3, 2, 1}))
|
||||
assert.Equal(false, IsAscending([]int{2, 1, 3, 4, 5}))
|
||||
}
|
||||
|
||||
func TestIsDescending(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsDescending")
|
||||
|
||||
assert.Equal(true, IsDescending([]int{5, 4, 3, 2, 1}))
|
||||
assert.Equal(false, IsDescending([]int{1, 2, 3, 4, 5}))
|
||||
assert.Equal(false, IsDescending([]int{2, 1, 3, 4, 5}))
|
||||
}
|
||||
|
||||
func TestIsSorted(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsSorted")
|
||||
|
||||
assert.Equal(true, IsSorted([]int{5, 4, 3, 2, 1}))
|
||||
assert.Equal(true, IsSorted([]int{1, 2, 3, 4, 5}))
|
||||
assert.Equal(false, IsSorted([]int{2, 1, 3, 4, 5}))
|
||||
}
|
||||
|
||||
func TestIsSortedByKey(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsSortedByKey")
|
||||
|
||||
assert.Equal(true, IsSortedByKey([]string{"a", "ab", "abc"}, func(s string) int {
|
||||
return len(s)
|
||||
}))
|
||||
|
||||
assert.Equal(true, IsSortedByKey([]string{"abc", "ab", "a"}, func(s string) int {
|
||||
return len(s)
|
||||
}))
|
||||
|
||||
assert.Equal(false, IsSortedByKey([]string{"abc", "a", "ab"}, func(s string) int {
|
||||
return len(s)
|
||||
}))
|
||||
}
|
||||
|
||||
func TestSort(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSort")
|
||||
|
||||
|
||||
113
stream/stream.go
113
stream/stream.go
@@ -10,6 +10,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
"golang.org/x/exp/constraints"
|
||||
)
|
||||
|
||||
@@ -23,7 +24,7 @@ import (
|
||||
// Map(mapper func(item T) T) StreamI[T]
|
||||
// Peek(consumer func(item T)) StreamI[T]
|
||||
|
||||
// Sort(less func(a, b T) bool) StreamI[T]
|
||||
// Sorted(less func(a, b T) bool) StreamI[T]
|
||||
// Max(less func(a, b T) bool) (T, bool)
|
||||
// Min(less func(a, b T) bool) (T, bool)
|
||||
|
||||
@@ -43,7 +44,7 @@ import (
|
||||
|
||||
// // part of methods custom extension
|
||||
// Reverse() StreamI[T]
|
||||
// Range(start, end int64) StreamI[T]
|
||||
// Range(start, end int) StreamI[T]
|
||||
// Concat(streams ...StreamI[T]) StreamI[T]
|
||||
// }
|
||||
|
||||
@@ -72,12 +73,12 @@ func Generate[T any](generator func() func() (item T, ok bool)) stream[T] {
|
||||
return FromSlice(source)
|
||||
}
|
||||
|
||||
// FromSlice create stream from slice.
|
||||
// FromSlice creates stream from slice.
|
||||
func FromSlice[T any](source []T) stream[T] {
|
||||
return stream[T]{source: source}
|
||||
}
|
||||
|
||||
// FromChannel create stream from channel.
|
||||
// FromChannel creates stream from channel.
|
||||
func FromChannel[T any](source <-chan T) stream[T] {
|
||||
s := make([]T, 0)
|
||||
|
||||
@@ -88,7 +89,7 @@ func FromChannel[T any](source <-chan T) stream[T] {
|
||||
return FromSlice(s)
|
||||
}
|
||||
|
||||
// FromRange create a number stream from start to end. both start and end are included. [start, end]
|
||||
// FromRange creates a number stream from start to end. both start and end are included. [start, end]
|
||||
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T] {
|
||||
if end < start {
|
||||
panic("stream.FromRange: param start should be before param end")
|
||||
@@ -106,6 +107,16 @@ func FromRange[T constraints.Integer | constraints.Float](start, end, step T) st
|
||||
return FromSlice(source)
|
||||
}
|
||||
|
||||
// Concat creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream.
|
||||
func Concat[T any](a, b stream[T]) stream[T] {
|
||||
source := make([]T, 0)
|
||||
|
||||
source = append(source, a.source...)
|
||||
source = append(source, b.source...)
|
||||
|
||||
return FromSlice(source)
|
||||
}
|
||||
|
||||
// Distinct returns a stream that removes the duplicated items.
|
||||
func (s stream[T]) Distinct() stream[T] {
|
||||
source := make([]T, 0)
|
||||
@@ -255,6 +266,98 @@ func (s stream[T]) Count() int {
|
||||
return len(s.source)
|
||||
}
|
||||
|
||||
// FindFirst returns the first element of this stream and true, or zero value and false if the stream is empty.
|
||||
func (s stream[T]) FindFirst() (T, bool) {
|
||||
var result T
|
||||
|
||||
if s.source == nil || len(s.source) == 0 {
|
||||
return result, false
|
||||
}
|
||||
|
||||
return s.source[0], true
|
||||
}
|
||||
|
||||
// Reverse returns a stream whose elements are reverse order of given stream.
|
||||
func (s stream[T]) Reverse() stream[T] {
|
||||
l := len(s.source)
|
||||
source := make([]T, l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
source[i] = s.source[l-1-i]
|
||||
}
|
||||
return FromSlice(source)
|
||||
}
|
||||
|
||||
// Range returns a stream whose elements are in the range from start(included) to end(excluded) original stream.
|
||||
func (s stream[T]) Range(start, end int) stream[T] {
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
if end < 0 {
|
||||
end = 0
|
||||
}
|
||||
if start >= end {
|
||||
return FromSlice([]T{})
|
||||
}
|
||||
|
||||
source := make([]T, 0)
|
||||
|
||||
if end > len(s.source) {
|
||||
end = len(s.source)
|
||||
}
|
||||
|
||||
for i := start; i < end; i++ {
|
||||
source = append(source, s.source[i])
|
||||
}
|
||||
|
||||
return FromSlice(source)
|
||||
}
|
||||
|
||||
// Sorted returns a stream consisting of the elements of this stream, sorted according to the provided less function.
|
||||
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T] {
|
||||
source := []T{}
|
||||
source = append(source, s.source...)
|
||||
|
||||
slice.SortBy(source, less)
|
||||
|
||||
return FromSlice(source)
|
||||
}
|
||||
|
||||
// Max returns the maximum element of this stream according to the provided less function.
|
||||
// less: a > b
|
||||
func (s stream[T]) Max(less func(a, b T) bool) (T, bool) {
|
||||
var max T
|
||||
|
||||
if len(s.source) == 0 {
|
||||
return max, false
|
||||
}
|
||||
|
||||
for i, v := range s.source {
|
||||
if less(v, max) || i == 0 {
|
||||
max = v
|
||||
}
|
||||
}
|
||||
return max, true
|
||||
}
|
||||
|
||||
// Min returns the minimum element of this stream according to the provided less function.
|
||||
// less: a < b
|
||||
func (s stream[T]) Min(less func(a, b T) bool) (T, bool) {
|
||||
var min T
|
||||
|
||||
if len(s.source) == 0 {
|
||||
return min, false
|
||||
}
|
||||
|
||||
for i, v := range s.source {
|
||||
if less(v, min) || i == 0 {
|
||||
min = v
|
||||
}
|
||||
}
|
||||
|
||||
return min, true
|
||||
}
|
||||
|
||||
// ToSlice return the elements in the stream.
|
||||
func (s stream[T]) ToSlice() []T {
|
||||
return s.source
|
||||
|
||||
@@ -247,3 +247,92 @@ func TestStream_Reduce(t *testing.T) {
|
||||
|
||||
assert.Equal(6, result)
|
||||
}
|
||||
|
||||
func TestStream_FindFirst(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStream_FindFirst")
|
||||
|
||||
stream := FromSlice([]int{1, 2, 3})
|
||||
|
||||
result, ok := stream.FindFirst()
|
||||
|
||||
assert.Equal(1, result)
|
||||
assert.Equal(true, ok)
|
||||
}
|
||||
|
||||
func TestStream_Reverse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStream_Reverse")
|
||||
|
||||
s := FromSlice([]int{1, 2, 3})
|
||||
|
||||
rs := s.Reverse()
|
||||
|
||||
assert.Equal([]int{3, 2, 1}, rs.ToSlice())
|
||||
}
|
||||
|
||||
func TestStream_Range(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStream_Range")
|
||||
|
||||
s := FromSlice([]int{1, 2, 3})
|
||||
|
||||
s1 := s.Range(-1, 0)
|
||||
assert.Equal([]int{}, s1.ToSlice())
|
||||
|
||||
s2 := s.Range(0, -1)
|
||||
assert.Equal([]int{}, s2.ToSlice())
|
||||
|
||||
s3 := s.Range(0, 0)
|
||||
assert.Equal([]int{}, s3.ToSlice())
|
||||
|
||||
s4 := s.Range(1, 1)
|
||||
assert.Equal([]int{}, s4.ToSlice())
|
||||
|
||||
s5 := s.Range(0, 1)
|
||||
assert.Equal([]int{1}, s5.ToSlice())
|
||||
|
||||
s6 := s.Range(0, 4)
|
||||
assert.Equal([]int{1, 2, 3}, s6.ToSlice())
|
||||
}
|
||||
|
||||
func TestStream_Concat(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStream_Concat")
|
||||
|
||||
s1 := FromSlice([]int{1, 2, 3})
|
||||
s2 := FromSlice([]int{4, 5, 6})
|
||||
|
||||
s := Concat(s1, s2)
|
||||
|
||||
assert.Equal([]int{1, 2, 3, 4, 5, 6}, s.ToSlice())
|
||||
}
|
||||
|
||||
func TestStream_Sorted(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStream_Sorted")
|
||||
|
||||
s := FromSlice([]int{4, 2, 1, 3})
|
||||
|
||||
s1 := s.Sorted(func(a, b int) bool { return a < b })
|
||||
|
||||
assert.Equal([]int{4, 2, 1, 3}, s.ToSlice())
|
||||
assert.Equal([]int{1, 2, 3, 4}, s1.ToSlice())
|
||||
}
|
||||
|
||||
func TestStream_Max(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStream_Max")
|
||||
|
||||
s := FromSlice([]int{4, 2, 1, 3})
|
||||
|
||||
max, ok := s.Max(func(a, b int) bool { return a > b })
|
||||
|
||||
assert.Equal(4, max)
|
||||
assert.Equal(true, ok)
|
||||
}
|
||||
|
||||
func TestStream_Min(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStream_Min")
|
||||
|
||||
s := FromSlice([]int{4, 2, 1, 3})
|
||||
|
||||
max, ok := s.Max(func(a, b int) bool { return a < b })
|
||||
|
||||
assert.Equal(1, max)
|
||||
assert.Equal(true, ok)
|
||||
}
|
||||
|
||||
@@ -281,6 +281,10 @@ func IsZeroValue(value any) bool {
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(value)
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
rv = rv.Elem()
|
||||
}
|
||||
|
||||
if !rv.IsValid() {
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user