mirror of
https://github.com/duke-git/lancet.git
synced 2026-03-01 00:35:28 +08:00
Compare commits
8 Commits
v2.1.18
...
c53d541a6b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c53d541a6b | ||
|
|
5b9b4c4344 | ||
|
|
6e7300bbbf | ||
|
|
3685aee02b | ||
|
|
046f3e0bf9 | ||
|
|
c01c9d14b4 | ||
|
|
f198191063 | ||
|
|
8bdd46bda4 |
@@ -711,12 +711,16 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
|||||||
[[play](https://go.dev/play/p/akLWz0EqOSM)]
|
[[play](https://go.dev/play/p/akLWz0EqOSM)]
|
||||||
- **<big>AngleToRadian</big>** : converts angle value to radian value.
|
- **<big>AngleToRadian</big>** : converts angle value to radian value.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#AngleToRadian)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#AngleToRadian)]
|
||||||
|
[[play](https://go.dev/play/p/CIvlICqrHql)]
|
||||||
- **<big>RadianToAngle</big>** : converts radian value to angle value.
|
- **<big>RadianToAngle</big>** : converts radian value to angle value.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RadianToAngle)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RadianToAngle)]
|
||||||
|
[[play](https://go.dev/play/p/dQtmOTUOMgi)]
|
||||||
- **<big>PointDistance</big>** : get two points distance.
|
- **<big>PointDistance</big>** : get two points distance.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#PointDistance)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#PointDistance)]
|
||||||
|
[[play](https://go.dev/play/p/RrG4JIaziM8)]
|
||||||
- **<big>IsPrime</big>** : checks if number is prime number.
|
- **<big>IsPrime</big>** : checks if number is prime number.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#IsPrime)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#IsPrime)]
|
||||||
|
[[play](https://go.dev/play/p/Rdd8UTHZJ7u)]
|
||||||
|
|
||||||
### 13. Netutil package contains functions to get net information and send http request.
|
### 13. Netutil package contains functions to get net information and send http request.
|
||||||
|
|
||||||
@@ -1150,6 +1154,8 @@ import "github.com/duke-git/lancet/v2/strutil"
|
|||||||
[[play](https://go.dev/play/p/bj7_odx3vRf)]
|
[[play](https://go.dev/play/p/bj7_odx3vRf)]
|
||||||
- **<big>RemoveNonPrintable</big>** : remove non-printable characters from a string.
|
- **<big>RemoveNonPrintable</big>** : remove non-printable characters from a string.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#RemoveNonPrintable)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#RemoveNonPrintable)]
|
||||||
|
[[play](https://go.dev/play/p/og47F5x_jTZ)]
|
||||||
|
|
||||||
|
|
||||||
### 19. System package contain some functions about os, runtime, shell command.
|
### 19. System package contain some functions about os, runtime, shell command.
|
||||||
|
|
||||||
@@ -1281,8 +1287,10 @@ import "github.com/duke-git/lancet/v2/validator"
|
|||||||
[[play](https://go.dev/play/p/E2nt3unlmzP)]
|
[[play](https://go.dev/play/p/E2nt3unlmzP)]
|
||||||
- **<big>IsASCII</big>** : checks if string is all ASCII char.
|
- **<big>IsASCII</big>** : checks if string is all ASCII char.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsASCII)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsASCII)]
|
||||||
|
[[play](https://go.dev/play/p/hfQNPLX0jNa)]
|
||||||
- **<big>IsPrintable</big>** : checks if string is all printable chars.
|
- **<big>IsPrintable</big>** : checks if string is all printable chars.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsPrintable)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsPrintable)]
|
||||||
|
[[play](https://go.dev/play/p/Pe1FE2gdtTP)]
|
||||||
|
|
||||||
### 21. xerror package implements helpers for errors.
|
### 21. xerror package implements helpers for errors.
|
||||||
|
|
||||||
|
|||||||
@@ -710,12 +710,16 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
|||||||
[[play](https://go.dev/play/p/akLWz0EqOSM)]
|
[[play](https://go.dev/play/p/akLWz0EqOSM)]
|
||||||
- **<big>AngleToRadian</big>** : 将角度值转为弧度值。
|
- **<big>AngleToRadian</big>** : 将角度值转为弧度值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#AngleToRadian)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#AngleToRadian)]
|
||||||
|
[[play](https://go.dev/play/p/CIvlICqrHql)]
|
||||||
- **<big>RadianToAngle</big>** : 将弧度值转为角度值。
|
- **<big>RadianToAngle</big>** : 将弧度值转为角度值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RadianToAngle)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RadianToAngle)]
|
||||||
|
[[play](https://go.dev/play/p/dQtmOTUOMgi)]
|
||||||
- **<big>PointDistance</big>** : 计算两个坐标点的距离。
|
- **<big>PointDistance</big>** : 计算两个坐标点的距离。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#PointDistance)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#PointDistance)]
|
||||||
|
[[play](https://go.dev/play/p/RrG4JIaziM8)]
|
||||||
- **<big>IsPrime</big>** : 判断质数。
|
- **<big>IsPrime</big>** : 判断质数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#IsPrime)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#IsPrime)]
|
||||||
|
[[play](https://go.dev/play/p/Rdd8UTHZJ7u)]
|
||||||
|
|
||||||
### 13. netutil 网络包支持获取 ip 地址,发送 http 请求。
|
### 13. netutil 网络包支持获取 ip 地址,发送 http 请求。
|
||||||
|
|
||||||
@@ -1152,6 +1156,7 @@ import "github.com/duke-git/lancet/v2/strutil"
|
|||||||
[[play](https://go.dev/play/p/bj7_odx3vRf)]
|
[[play](https://go.dev/play/p/bj7_odx3vRf)]
|
||||||
- **<big>RemoveNonPrintable</big>** : 删除字符串中不可打印的字符。
|
- **<big>RemoveNonPrintable</big>** : 删除字符串中不可打印的字符。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#RemoveNonPrintable)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#RemoveNonPrintable)]
|
||||||
|
[[play](https://go.dev/play/p/og47F5x_jTZ)]
|
||||||
|
|
||||||
### 19. system 包含 os, runtime, shell command 的相关函数。
|
### 19. system 包含 os, runtime, shell command 的相关函数。
|
||||||
|
|
||||||
@@ -1283,8 +1288,10 @@ import "github.com/duke-git/lancet/v2/validator"
|
|||||||
[[play](https://go.dev/play/p/E2nt3unlmzP)]
|
[[play](https://go.dev/play/p/E2nt3unlmzP)]
|
||||||
- **<big>IsASCII</big>** : 验证字符串全部为 ASCII 字符。
|
- **<big>IsASCII</big>** : 验证字符串全部为 ASCII 字符。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsASCII)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsASCII)]
|
||||||
|
[[play](https://go.dev/play/p/hfQNPLX0jNa)]
|
||||||
- **<big>IsPrintable</big>** : 检查字符串是否全部为可打印字符。
|
- **<big>IsPrintable</big>** : 检查字符串是否全部为可打印字符。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsPrintable)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsPrintable)]
|
||||||
|
[[play](https://go.dev/play/p/Pe1FE2gdtTP)]
|
||||||
|
|
||||||
### 21. xerror 包实现一些错误处理函数
|
### 21. xerror 包实现一些错误处理函数
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
- [CreateFile](#CreateFile)
|
- [CreateFile](#CreateFile)
|
||||||
- [CreateDir](#CreateDir)
|
- [CreateDir](#CreateDir)
|
||||||
- [CopyFile](#CopyFile)
|
- [CopyFile](#CopyFile)
|
||||||
|
- [CurrentPath](#CurrentPath)
|
||||||
- [FileMode](#FileMode)
|
- [FileMode](#FileMode)
|
||||||
- [MiMeType](#MiMeType)
|
- [MiMeType](#MiMeType)
|
||||||
- [IsExist](#IsExist)
|
- [IsExist](#IsExist)
|
||||||
@@ -151,6 +152,32 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="CurrentPath">CurrentPath</span>
|
||||||
|
|
||||||
|
<p>return current absolute path.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func CurrentPath() string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
absPath := CurrentPath()
|
||||||
|
fmt.Println(absPath)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="FileMode">FileMode</span>
|
### <span id="FileMode">FileMode</span>
|
||||||
|
|
||||||
<p>Return file mode infomation.</p>
|
<p>Return file mode infomation.</p>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
- [CreateFile](#CreateFile)
|
- [CreateFile](#CreateFile)
|
||||||
- [CreateDir](#CreateDir)
|
- [CreateDir](#CreateDir)
|
||||||
- [CopyFile](#CopyFile)
|
- [CopyFile](#CopyFile)
|
||||||
|
- [CurrentPath](#CurrentPath)
|
||||||
- [FileMode](#FileMode)
|
- [FileMode](#FileMode)
|
||||||
- [MiMeType](#MiMeType)
|
- [MiMeType](#MiMeType)
|
||||||
- [IsExist](#IsExist)
|
- [IsExist](#IsExist)
|
||||||
@@ -150,6 +151,32 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="CurrentPath">CurrentPath</span>
|
||||||
|
|
||||||
|
<p>返回当前位置的绝对路径。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func CurrentPath() string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
absPath := CurrentPath()
|
||||||
|
fmt.Println(absPath)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="FileMode">FileMode</span>
|
### <span id="FileMode">FileMode</span>
|
||||||
|
|
||||||
<p>获取文件mode信息</p>
|
<p>获取文件mode信息</p>
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ import (
|
|||||||
- [Merge](#Merge)
|
- [Merge](#Merge)
|
||||||
- [Reverse](#Reverse)
|
- [Reverse](#Reverse)
|
||||||
- [Reduce](#Reduce)
|
- [Reduce](#Reduce)
|
||||||
|
- [ReduceBy](#ReduceBy)
|
||||||
|
- [ReduceRight](#ReduceRight)
|
||||||
- [Replace](#Replace)
|
- [Replace](#Replace)
|
||||||
- [ReplaceAll](#ReplaceAll)
|
- [ReplaceAll](#ReplaceAll)
|
||||||
- [Repeat](#Repeat)
|
- [Repeat](#Repeat)
|
||||||
@@ -1504,6 +1506,72 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="ReduceBy">ReduceBy</span>
|
||||||
|
|
||||||
|
<p>Produces a value from slice by accumulating the result of each element as passed through the reducer function.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ReduceBy[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := slice.ReduceBy([]int{1, 2, 3, 4}, 0, func(_ int, item int, agg int) int {
|
||||||
|
return agg + item
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := slice.ReduceBy([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 10
|
||||||
|
// 1234
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ReduceRight">ReduceRight</span>
|
||||||
|
|
||||||
|
<p>ReduceRight is like ReduceBy, but it iterates over elements of slice from right to left.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ReduceRight[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result := slice.ReduceRight([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 4321
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="Replace">Replace</span>
|
### <span id="Replace">Replace</span>
|
||||||
|
|
||||||
<p>Returns a copy of the slice with the first n non-overlapping instances of old replaced by new.</p>
|
<p>Returns a copy of the slice with the first n non-overlapping instances of old replaced by new.</p>
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ import (
|
|||||||
- [Merge](#Merge)
|
- [Merge](#Merge)
|
||||||
- [Reverse](#Reverse)
|
- [Reverse](#Reverse)
|
||||||
- [Reduce](#Reduce)
|
- [Reduce](#Reduce)
|
||||||
|
- [ReduceBy](#ReduceBy)
|
||||||
|
- [ReduceRight](#ReduceRight)
|
||||||
- [Replace](#Replace)
|
- [Replace](#Replace)
|
||||||
- [ReplaceAll](#ReplaceAll)
|
- [ReplaceAll](#ReplaceAll)
|
||||||
- [Repeat](#Repeat)
|
- [Repeat](#Repeat)
|
||||||
@@ -1505,6 +1507,72 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="ReduceBy">ReduceBy</span>
|
||||||
|
|
||||||
|
<p>对切片中执行reduce操作。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ReduceBy[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := slice.ReduceBy([]int{1, 2, 3, 4}, 0, func(_ int, item int, agg int) int {
|
||||||
|
return agg + item
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := slice.ReduceBy([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 10
|
||||||
|
// 1234
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ReduceRight">ReduceRight</span>
|
||||||
|
|
||||||
|
<p>类似ReduceBy操作,迭代切片元素顺序从右至左。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ReduceRight[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result := slice.ReduceRight([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 4321
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="Replace">Replace</span>
|
### <span id="Replace">Replace</span>
|
||||||
|
|
||||||
<p>返回切片的副本,其中前n个不重叠的old替换为new</p>
|
<p>返回切片的副本,其中前n个不重叠的old替换为new</p>
|
||||||
|
|||||||
907
docs/stream.md
Normal file
907
docs/stream.md
Normal file
@@ -0,0 +1,907 @@
|
|||||||
|
# Stream
|
||||||
|
|
||||||
|
Package stream implements a sequence of elements supporting sequential and operations. This package is an experiment to explore if stream in go can work as the way java does. it's feature is very limited.
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## Source:
|
||||||
|
|
||||||
|
- [https://github.com/duke-git/lancet/blob/main/stream/stream.go](https://github.com/duke-git/lancet/blob/main/stream/stream.go)
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## Usage:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## Index
|
||||||
|
|
||||||
|
- [Of](#Of)
|
||||||
|
- [FromSlice](#FromSlice)
|
||||||
|
- [FromChannel](#FromChannel)
|
||||||
|
- [FromRange](#FromRange)
|
||||||
|
- [Generate](#Generate)
|
||||||
|
- [Concat](#Concat)
|
||||||
|
- [Distinct](#Distinct)
|
||||||
|
- [Filter](#Filter)
|
||||||
|
- [Map](#Map)
|
||||||
|
- [Peek](#Peek)
|
||||||
|
- [Skip](#Skip)
|
||||||
|
- [Limit](#Limit)
|
||||||
|
- [Reverse](#Reverse)
|
||||||
|
- [Range](#Range)
|
||||||
|
- [Sorted](#Sorted)
|
||||||
|
- [ForEach](#ForEach)
|
||||||
|
- [Reduce](#Reduce)
|
||||||
|
- [FindFirst](#FindFirst)
|
||||||
|
- [Max](#Max)
|
||||||
|
- [Min](#Min)
|
||||||
|
- [AllMatch](#AllMatch)
|
||||||
|
- [AnyMatch](#AnyMatch)
|
||||||
|
- [NoneMatch](#NoneMatch)
|
||||||
|
- [Count](#Count)
|
||||||
|
- [ToSlice](#ToSlice)
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
### <span id="Of">Of</span>
|
||||||
|
|
||||||
|
<p>Creates a stream whose elements are the specified values.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Of[T any](elems ...T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.Of(1, 2, 3)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FromSlice">FromSlice</span>
|
||||||
|
|
||||||
|
<p>Creates a stream from slice.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FromSlice[T any](source []T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FromChannel">FromChannel</span>
|
||||||
|
|
||||||
|
<p>Creates a stream from channel.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FromChannel[T any](source <-chan T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ch := make(chan int)
|
||||||
|
go func() {
|
||||||
|
for i := 1; i < 4; i++ {
|
||||||
|
ch <- i
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
}()
|
||||||
|
|
||||||
|
s := stream.FromChannel(ch)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FromRange">FromRange</span>
|
||||||
|
|
||||||
|
<p>Creates a number stream from start to end. both start and end are included. [start, end]</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.FromRange(1, 5, 1)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4 5]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Generate">Generate</span>
|
||||||
|
|
||||||
|
<p>Creates a stream where each element is generated by the provided generater function.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Generate[T any](generator func() func() (item T, ok bool)) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n := 0
|
||||||
|
max := 4
|
||||||
|
|
||||||
|
generator := func() func() (int, bool) {
|
||||||
|
return func() (int, bool) {
|
||||||
|
n++
|
||||||
|
return n, n < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s := stream.Generate(generator)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Concat">Concat</span>
|
||||||
|
|
||||||
|
<p>Creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Concat[T any](a, b stream[T]) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s1 := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := stream.FromSlice([]int{4, 5, 6})
|
||||||
|
|
||||||
|
s := Concat(s1, s2)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4 5 6]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Distinct">Distinct</span>
|
||||||
|
|
||||||
|
<p>Creates returns a stream that removes the duplicated items. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Distinct() stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 2, 3, 3, 3})
|
||||||
|
distinct := original.Distinct()
|
||||||
|
|
||||||
|
data1 := original.ToSlice()
|
||||||
|
data2 := distinct.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data1)
|
||||||
|
fmt.Println(data2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 2 3 3 3]
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Filter">Filter</span>
|
||||||
|
|
||||||
|
<p>Returns a stream consisting of the elements of this stream that match the given predicate. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Filter(predicate func(item T) bool) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3, 4, 5})
|
||||||
|
|
||||||
|
isEven := func(n int) bool {
|
||||||
|
return n%2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
even := original.Filter(isEven)
|
||||||
|
|
||||||
|
fmt.Println(even.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Map">Map</span>
|
||||||
|
|
||||||
|
<p>Returns a stream consisting of the elements of this stream that apply the given function to elements of stream. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Map(mapper func(item T) T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
addOne := func(n int) int {
|
||||||
|
return n + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
increament := original.Map(addOne)
|
||||||
|
|
||||||
|
fmt.Println(increament.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Peek">Peek</span>
|
||||||
|
|
||||||
|
<p>Returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Peek(consumer func(item T)) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
data := []string{}
|
||||||
|
peekStream := original.Peek(func(n int) {
|
||||||
|
data = append(data, fmt.Sprint("value", n))
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(original.ToSlice())
|
||||||
|
fmt.Println(peekStream.ToSlice())
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
// [1 2 3]
|
||||||
|
// [value1 value2 value3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Skip">Skip</span>
|
||||||
|
|
||||||
|
<p>Returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream. If this stream contains fewer than n elements then an empty stream will be returned. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Skip(n int) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
|
s1 := original.Skip(-1)
|
||||||
|
s2 := original.Skip(0)
|
||||||
|
s3 := original.Skip(1)
|
||||||
|
s4 := original.Skip(5)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [2 3 4]
|
||||||
|
// []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Limit">Limit</span>
|
||||||
|
|
||||||
|
<p>Returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Limit(maxSize int) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
|
s1 := original.Limit(-1)
|
||||||
|
s2 := original.Limit(0)
|
||||||
|
s3 := original.Limit(1)
|
||||||
|
s4 := original.Limit(5)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []
|
||||||
|
// []
|
||||||
|
// [1]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Reverse">Reverse</span>
|
||||||
|
|
||||||
|
<p>Returns a stream whose elements are reverse order of given stream. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Reverse() stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
reverse := original.Reverse()
|
||||||
|
|
||||||
|
fmt.Println(reverse.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [3 2 1]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Range">Range</span>
|
||||||
|
|
||||||
|
<p>Returns a stream whose elements are in the range from start(included) to end(excluded) original stream.<b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Range(start, end int) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
s1 := original.Range(0, 0)
|
||||||
|
s2 := original.Range(0, 1)
|
||||||
|
s3 := original.Range(0, 3)
|
||||||
|
s4 := original.Range(1, 2)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []
|
||||||
|
// [1]
|
||||||
|
// [1 2 3]
|
||||||
|
// [2]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Sorted">Sorted</span>
|
||||||
|
|
||||||
|
<p>Returns a stream consisting of the elements of this stream, sorted according to the provided less function.<b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
sorted := original.Sorted(func(a, b int) bool { return a < b })
|
||||||
|
|
||||||
|
fmt.Println(original.ToSlice())
|
||||||
|
fmt.Println(sorted.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [4 2 1 3]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ForEach">ForEach</span>
|
||||||
|
|
||||||
|
<p>Performs an action for each element of this stream.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) ForEach(action func(item T))
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result := 0
|
||||||
|
original.ForEach(func(item int) {
|
||||||
|
result += item
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 6
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Reduce">Reduce</span>
|
||||||
|
|
||||||
|
<p>Performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Reduce(initial T, accumulator func(a, b T) T) T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result := original.Reduce(0, func(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 6
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FindFirst">FindFirst</span>
|
||||||
|
|
||||||
|
<p>Returns the first element of this stream and true, or zero value and false if the stream is empty.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) FindFirst() (T, bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result, ok := original.FindFirst()
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Max">Max</span>
|
||||||
|
|
||||||
|
<p>Returns the maximum element of this stream according to the provided less function. less fuction: a > b</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Max(less func(a, b T) bool) (T, bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
max, ok := original.Max(func(a, b int) bool { return a > b })
|
||||||
|
|
||||||
|
fmt.Println(max)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 4
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Min">Min</span>
|
||||||
|
|
||||||
|
<p>Returns the minimum element of this stream according to the provided less function. less fuction: a < b</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Min(less func(a, b T) bool) (T, bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
min, ok := original.Min(func(a, b int) bool { return a < b })
|
||||||
|
|
||||||
|
fmt.Println(min)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="AllMatch">AllMatch</span>
|
||||||
|
|
||||||
|
<p>Returns whether all elements of this stream match the provided predicate.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) AllMatch(predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.AllMatch(func(item int) bool {
|
||||||
|
return item > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.AllMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="AnyMatch">AnyMatch</span>
|
||||||
|
|
||||||
|
<p>Returns whether any elements of this stream match the provided predicate.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.AnyMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.AnyMatch(func(item int) bool {
|
||||||
|
return item > 3
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="NoneMatch">NoneMatch</span>
|
||||||
|
|
||||||
|
<p>Returns whether no elements of this stream match the provided predicate.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.NoneMatch(func(item int) bool {
|
||||||
|
return item > 3
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.NoneMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Count">Count</span>
|
||||||
|
|
||||||
|
<p>Returns the count of elements in the stream.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Count() int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s1 := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := stream.FromSlice([]int{})
|
||||||
|
|
||||||
|
fmt.Println(s1.Count())
|
||||||
|
fmt.Println(s2.Count())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 3
|
||||||
|
// 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToSlice">ToSlice</span>
|
||||||
|
|
||||||
|
<p>Returns the elements in the stream.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) ToSlice() []T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.Of(1, 2, 3)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
907
docs/stream_zh-CN.md
Normal file
907
docs/stream_zh-CN.md
Normal file
@@ -0,0 +1,907 @@
|
|||||||
|
# Strutil
|
||||||
|
|
||||||
|
Stream 实现,该包仅验证简单 go stream 实现,功能有限。
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## 源码:
|
||||||
|
|
||||||
|
- [https://github.com/duke-git/lancet/blob/main/stream/stream.go](https://github.com/duke-git/lancet/blob/main/stream/stream.go)
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## 用法:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## 目录
|
||||||
|
|
||||||
|
- [Of](#Of)
|
||||||
|
- [FromSlice](#FromSlice)
|
||||||
|
- [FromChannel](#FromChannel)
|
||||||
|
- [FromRange](#FromRange)
|
||||||
|
- [Generate](#Generate)
|
||||||
|
- [Concat](#Concat)
|
||||||
|
- [Distinct](#Distinct)
|
||||||
|
- [Filter](#Filter)
|
||||||
|
- [Map](#Map)
|
||||||
|
- [Peek](#Peek)
|
||||||
|
- [Skip](#Skip)
|
||||||
|
- [Limit](#Limit)
|
||||||
|
- [Reverse](#Reverse)
|
||||||
|
- [Range](#Range)
|
||||||
|
- [Sorted](#Sorted)
|
||||||
|
- [ForEach](#ForEach)
|
||||||
|
- [Reduce](#Reduce)
|
||||||
|
- [FindFirst](#FindFirst)
|
||||||
|
- [Max](#Max)
|
||||||
|
- [Min](#Min)
|
||||||
|
- [AllMatch](#AllMatch)
|
||||||
|
- [AnyMatch](#AnyMatch)
|
||||||
|
- [NoneMatch](#NoneMatch)
|
||||||
|
- [Count](#Count)
|
||||||
|
- [ToSlice](#ToSlice)
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## 文档
|
||||||
|
|
||||||
|
### <span id="Of">Of</span>
|
||||||
|
|
||||||
|
<p>创建元素为指定值的stream。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Of[T any](elems ...T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.Of(1, 2, 3)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FromSlice">FromSlice</span>
|
||||||
|
|
||||||
|
<p>从切片创建stream。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FromSlice[T any](source []T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FromChannel">FromChannel</span>
|
||||||
|
|
||||||
|
<p>从通道创建stream。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FromChannel[T any](source <-chan T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ch := make(chan int)
|
||||||
|
go func() {
|
||||||
|
for i := 1; i < 4; i++ {
|
||||||
|
ch <- i
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
}()
|
||||||
|
|
||||||
|
s := stream.FromChannel(ch)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FromRange">FromRange</span>
|
||||||
|
|
||||||
|
<p>指定一个范围创建stream, 范围两端点值都包括在内。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.FromRange(1, 5, 1)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4 5]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Generate">Generate</span>
|
||||||
|
|
||||||
|
<p>创建一个stream,其中每个元素都由提供的生成器函数生成</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Generate[T any](generator func() func() (item T, ok bool)) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n := 0
|
||||||
|
max := 4
|
||||||
|
|
||||||
|
generator := func() func() (int, bool) {
|
||||||
|
return func() (int, bool) {
|
||||||
|
n++
|
||||||
|
return n, n < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s := stream.Generate(generator)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Concat">Concat</span>
|
||||||
|
|
||||||
|
<p>创建一个延迟连接stream,其元素是第一个stream的所有元素,后跟第二个stream的全部元素。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Concat[T any](a, b stream[T]) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s1 := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := stream.FromSlice([]int{4, 5, 6})
|
||||||
|
|
||||||
|
s := Concat(s1, s2)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4 5 6]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Distinct">Distinct</span>
|
||||||
|
|
||||||
|
<p>创建并返回一个stream,用于删除重复的项。 <b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Distinct() stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 2, 3, 3, 3})
|
||||||
|
distinct := original.Distinct()
|
||||||
|
|
||||||
|
data1 := original.ToSlice()
|
||||||
|
data2 := distinct.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data1)
|
||||||
|
fmt.Println(data2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 2 3 3 3]
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Filter">Filter</span>
|
||||||
|
|
||||||
|
<p>返回一个通过判定函数的stream <b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Filter(predicate func(item T) bool) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3, 4, 5})
|
||||||
|
|
||||||
|
isEven := func(n int) bool {
|
||||||
|
return n%2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
even := original.Filter(isEven)
|
||||||
|
|
||||||
|
fmt.Println(even.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Map">Map</span>
|
||||||
|
|
||||||
|
<p>返回一个stream,该stream由将给定函数应用于源stream元素的元素组成。<b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Map(mapper func(item T) T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
addOne := func(n int) int {
|
||||||
|
return n + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
increament := original.Map(addOne)
|
||||||
|
|
||||||
|
fmt.Println(increament.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Peek">Peek</span>
|
||||||
|
|
||||||
|
<p>返回一个由源stream的元素组成的stream,并在从生成的stream中消耗元素时对每个元素执行所提供的操作。 <b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Peek(consumer func(item T)) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
data := []string{}
|
||||||
|
peekStream := original.Peek(func(n int) {
|
||||||
|
data = append(data, fmt.Sprint("value", n))
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(original.ToSlice())
|
||||||
|
fmt.Println(peekStream.ToSlice())
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
// [1 2 3]
|
||||||
|
// [value1 value2 value3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Skip">Skip</span>
|
||||||
|
|
||||||
|
<p>在丢弃stream的前n个元素后,返回由源stream的其余元素组成的stream。如果此stream包含的元素少于n个,则将返回一个空stream。<b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Skip(n int) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
|
s1 := original.Skip(-1)
|
||||||
|
s2 := original.Skip(0)
|
||||||
|
s3 := original.Skip(1)
|
||||||
|
s4 := original.Skip(5)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [2 3 4]
|
||||||
|
// []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Limit">Limit</span>
|
||||||
|
|
||||||
|
<p>返回由源stream的元素组成的stream,该stream被截断为长度不超过maxSize。<b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Limit(maxSize int) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
|
s1 := original.Limit(-1)
|
||||||
|
s2 := original.Limit(0)
|
||||||
|
s3 := original.Limit(1)
|
||||||
|
s4 := original.Limit(5)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []
|
||||||
|
// []
|
||||||
|
// [1]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Reverse">Reverse</span>
|
||||||
|
|
||||||
|
<p>返回元素与源stream的顺序相反的stream。<b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Reverse() stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
reverse := original.Reverse()
|
||||||
|
|
||||||
|
fmt.Println(reverse.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [3 2 1]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Range">Range</span>
|
||||||
|
|
||||||
|
<p>返回一个stream,该stream的元素在从源stream的开始(包含)到结束(排除)的范围内。<b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Range(start, end int) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
s1 := original.Range(0, 0)
|
||||||
|
s2 := original.Range(0, 1)
|
||||||
|
s3 := original.Range(0, 3)
|
||||||
|
s4 := original.Range(1, 2)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []
|
||||||
|
// [1]
|
||||||
|
// [1 2 3]
|
||||||
|
// [2]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Sorted">Sorted</span>
|
||||||
|
|
||||||
|
<p>返回一个stream,该stream由源stream的元素组成,并根据提供的less函数进行排序。<b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
sorted := original.Sorted(func(a, b int) bool { return a < b })
|
||||||
|
|
||||||
|
fmt.Println(original.ToSlice())
|
||||||
|
fmt.Println(sorted.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [4 2 1 3]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ForEach">ForEach</span>
|
||||||
|
|
||||||
|
<p>对stream的每个元素执行一个操作。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) ForEach(action func(item T))
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result := 0
|
||||||
|
original.ForEach(func(item int) {
|
||||||
|
result += item
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 6
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Reduce">Reduce</span>
|
||||||
|
|
||||||
|
<p>使用关联累加函数对stream的元素执行reduce操作,并reduce操作结果(如果有)。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Reduce(initial T, accumulator func(a, b T) T) T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result := original.Reduce(0, func(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 6
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FindFirst">FindFirst</span>
|
||||||
|
|
||||||
|
<p>返回此stream的第一个元素和true,如果stream为空,则返回零值和false。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) FindFirst() (T, bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result, ok := original.FindFirst()
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Max">Max</span>
|
||||||
|
|
||||||
|
<p>根据提供的less函数返回stream的最大元素。less 函数: a > b</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Max(less func(a, b T) bool) (T, bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
max, ok := original.Max(func(a, b int) bool { return a > b })
|
||||||
|
|
||||||
|
fmt.Println(max)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 4
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Min">Min</span>
|
||||||
|
|
||||||
|
<p>根据提供的less函数返回stream的最小元素。less函数: a < b</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Min(less func(a, b T) bool) (T, bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
min, ok := original.Min(func(a, b int) bool { return a < b })
|
||||||
|
|
||||||
|
fmt.Println(min)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="AllMatch">AllMatch</span>
|
||||||
|
|
||||||
|
<p>判断stream的所有元素是否全部匹配指定判定函数。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) AllMatch(predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.AllMatch(func(item int) bool {
|
||||||
|
return item > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.AllMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="AnyMatch">AnyMatch</span>
|
||||||
|
|
||||||
|
<p>判断stream是否包含匹配指定判定函数的元素。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.AnyMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.AnyMatch(func(item int) bool {
|
||||||
|
return item > 3
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="NoneMatch">NoneMatch</span>
|
||||||
|
|
||||||
|
<p>判断stream的元素是否全部不匹配指定的判定函数。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.NoneMatch(func(item int) bool {
|
||||||
|
return item > 3
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.NoneMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Count">Count</span>
|
||||||
|
|
||||||
|
<p>返回stream中元素的数量。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Count() int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s1 := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := stream.FromSlice([]int{})
|
||||||
|
|
||||||
|
fmt.Println(s1.Count())
|
||||||
|
fmt.Println(s2.Count())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 3
|
||||||
|
// 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToSlice">ToSlice</span>
|
||||||
|
|
||||||
|
<p>返回stream中的元素切片。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) ToSlice() []T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.Of(1, 2, 3)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -345,3 +346,15 @@ func MiMeType(file any) string {
|
|||||||
}
|
}
|
||||||
return mediatype
|
return mediatype
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CurrentPath return current absolute path.
|
||||||
|
// Play: todo
|
||||||
|
func CurrentPath() string {
|
||||||
|
var absPath string
|
||||||
|
_, filename, _, ok := runtime.Caller(1)
|
||||||
|
if ok {
|
||||||
|
absPath = path.Dir(filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
return absPath
|
||||||
|
}
|
||||||
|
|||||||
@@ -241,3 +241,8 @@ func TestListFileNames(t *testing.T) {
|
|||||||
expected := []string{"formatter.go", "formatter_example_test.go", "formatter_test.go"}
|
expected := []string{"formatter.go", "formatter_example_test.go", "formatter_test.go"}
|
||||||
assert.Equal(expected, filesInPath)
|
assert.Equal(expected, filesInPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCurrentPath(t *testing.T) {
|
||||||
|
absPath := CurrentPath()
|
||||||
|
t.Log(absPath)
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ package formatter
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
"github.com/duke-git/lancet/v2/strutil"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
"golang.org/x/exp/constraints"
|
"golang.org/x/exp/constraints"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,54 +18,29 @@ import (
|
|||||||
// Comma("12345", "$") => "$12,345", Comma(12345, "$") => "$12,345"
|
// Comma("12345", "$") => "$12,345", Comma(12345, "$") => "$12,345"
|
||||||
// Play: https://go.dev/play/p/eRD5k2vzUVX
|
// Play: https://go.dev/play/p/eRD5k2vzUVX
|
||||||
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string {
|
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string {
|
||||||
s, err := numberToString(value)
|
if validator.IsInt(value) {
|
||||||
if err != nil {
|
v, err := convertor.ToInt(value)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return symbol + commaInt(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if validator.IsFloat(value) {
|
||||||
|
v, err := convertor.ToFloat(value)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return symbol + commaFloat(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strutil.IsString(value) {
|
||||||
|
v := fmt.Sprintf("%v", value)
|
||||||
|
if validator.IsNumberStr(v) {
|
||||||
|
return symbol + commaStr(v)
|
||||||
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
dotIndex := strings.Index(s, ".")
|
return ""
|
||||||
if dotIndex != -1 {
|
|
||||||
return symbol + commaString(s[:dotIndex]) + s[dotIndex:]
|
|
||||||
}
|
|
||||||
|
|
||||||
return symbol + commaString(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func commaString(s string) string {
|
|
||||||
if len(s) <= 3 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
return commaString(s[:len(s)-3]) + "," + commaString(s[len(s)-3:])
|
|
||||||
}
|
|
||||||
|
|
||||||
func numberToString(value any) (string, error) {
|
|
||||||
switch reflect.TypeOf(value).Kind() {
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
|
||||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
||||||
return fmt.Sprintf("%v", value), nil
|
|
||||||
|
|
||||||
// todo: need to handle 12345678.9 => 1.23456789e+07
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return fmt.Sprintf("%v", value), nil
|
|
||||||
|
|
||||||
case reflect.String:
|
|
||||||
{
|
|
||||||
sv := fmt.Sprintf("%v", value)
|
|
||||||
if strings.Contains(sv, ".") {
|
|
||||||
_, err := strconv.ParseFloat(sv, 64)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return sv, nil
|
|
||||||
} else {
|
|
||||||
_, err := strconv.ParseInt(sv, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
return sv, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
85
formatter/formatter_internal.go
Normal file
85
formatter/formatter_internal.go
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
package formatter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// see https://github.com/dustin/go-humanize/blob/master/comma.go
|
||||||
|
func commaInt(v int64) string {
|
||||||
|
sign := ""
|
||||||
|
|
||||||
|
// Min int64 can't be negated to a usable value, so it has to be special cased.
|
||||||
|
if v == math.MinInt64 {
|
||||||
|
return "-9,223,372,036,854,775,808"
|
||||||
|
}
|
||||||
|
|
||||||
|
if v < 0 {
|
||||||
|
sign = "-"
|
||||||
|
v = 0 - v
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := []string{"", "", "", "", "", "", ""}
|
||||||
|
j := len(parts) - 1
|
||||||
|
|
||||||
|
for v > 999 {
|
||||||
|
parts[j] = strconv.FormatInt(v%1000, 10)
|
||||||
|
switch len(parts[j]) {
|
||||||
|
case 2:
|
||||||
|
parts[j] = "0" + parts[j]
|
||||||
|
case 1:
|
||||||
|
parts[j] = "00" + parts[j]
|
||||||
|
}
|
||||||
|
v = v / 1000
|
||||||
|
j--
|
||||||
|
}
|
||||||
|
parts[j] = strconv.Itoa(int(v))
|
||||||
|
return sign + strings.Join(parts[j:], ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
func commaFloat(v float64) string {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
if v < 0 {
|
||||||
|
buf.Write([]byte{'-'})
|
||||||
|
v = 0 - v
|
||||||
|
}
|
||||||
|
|
||||||
|
comma := []byte{','}
|
||||||
|
|
||||||
|
parts := strings.Split(strconv.FormatFloat(v, 'f', -1, 64), ".")
|
||||||
|
pos := 0
|
||||||
|
if len(parts[0])%3 != 0 {
|
||||||
|
pos += len(parts[0]) % 3
|
||||||
|
buf.WriteString(parts[0][:pos])
|
||||||
|
buf.Write(comma)
|
||||||
|
}
|
||||||
|
for ; pos < len(parts[0]); pos += 3 {
|
||||||
|
buf.WriteString(parts[0][pos : pos+3])
|
||||||
|
buf.Write(comma)
|
||||||
|
}
|
||||||
|
buf.Truncate(buf.Len() - 1)
|
||||||
|
|
||||||
|
if len(parts) > 1 {
|
||||||
|
buf.Write([]byte{'.'})
|
||||||
|
buf.WriteString(parts[1])
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func commaStr(s string) string {
|
||||||
|
dotIndex := strings.Index(s, ".")
|
||||||
|
if dotIndex != -1 {
|
||||||
|
return commaStrRecursive(s[:dotIndex]) + s[dotIndex:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return commaStrRecursive(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func commaStrRecursive(s string) string {
|
||||||
|
if len(s) <= 3 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return commaStrRecursive(s[:len(s)-3]) + "," + commaStrRecursive(s[len(s)-3:])
|
||||||
|
}
|
||||||
@@ -16,12 +16,13 @@ func TestComma(t *testing.T) {
|
|||||||
assert.Equal("12,345", Comma("12345", ""))
|
assert.Equal("12,345", Comma("12345", ""))
|
||||||
assert.Equal("12,345.6789", Comma("12345.6789", ""))
|
assert.Equal("12,345.6789", Comma("12345.6789", ""))
|
||||||
assert.Equal("123,456,789,000", Comma("123456789000", ""))
|
assert.Equal("123,456,789,000", Comma("123456789000", ""))
|
||||||
|
assert.Equal("12,345,678.9", Comma("12345678.9", ""))
|
||||||
|
|
||||||
assert.Equal("12,345", Comma(12345, ""))
|
assert.Equal("12,345", Comma(12345, ""))
|
||||||
assert.Equal("$12,345", Comma(12345, "$"))
|
assert.Equal("$12,345", Comma(12345, "$"))
|
||||||
assert.Equal("¥12,345", Comma(12345, "¥"))
|
assert.Equal("¥12,345", Comma(12345, "¥"))
|
||||||
assert.Equal("12,345.6789", Comma(12345.6789, ""))
|
assert.Equal("12,345.6789", Comma(12345.6789, ""))
|
||||||
assert.Equal("12,345.6789", Comma(+12345.6789, ""))
|
assert.Equal("12,345.6789", Comma(+12345.6789, ""))
|
||||||
// assert.Equal("12,345,678.9", Comma(12345678.9, ""))
|
assert.Equal("12,345,678.9", Comma(12345678.9, ""))
|
||||||
assert.Equal("123,456,789,000", Comma(123456789000, ""))
|
assert.Equal("123,456,789,000", Comma(123456789000, ""))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,21 +218,21 @@ func RangeWithStep[T constraints.Integer | constraints.Float](start, end, step T
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AngleToRadian converts angle value to radian value.
|
// AngleToRadian converts angle value to radian value.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/CIvlICqrHql
|
||||||
func AngleToRadian(angle float64) float64 {
|
func AngleToRadian(angle float64) float64 {
|
||||||
radian := angle * (math.Pi / 180)
|
radian := angle * (math.Pi / 180)
|
||||||
return radian
|
return radian
|
||||||
}
|
}
|
||||||
|
|
||||||
// RadianToAngle converts radian value to angle value.
|
// RadianToAngle converts radian value to angle value.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/dQtmOTUOMgi
|
||||||
func RadianToAngle(radian float64) float64 {
|
func RadianToAngle(radian float64) float64 {
|
||||||
angle := radian * (180 / math.Pi)
|
angle := radian * (180 / math.Pi)
|
||||||
return angle
|
return angle
|
||||||
}
|
}
|
||||||
|
|
||||||
// PointDistance get two points distance.
|
// PointDistance get two points distance.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/RrG4JIaziM8
|
||||||
func PointDistance(x1, y1, x2, y2 float64) float64 {
|
func PointDistance(x1, y1, x2, y2 float64) float64 {
|
||||||
a := x1 - x2
|
a := x1 - x2
|
||||||
b := y1 - y2
|
b := y1 - y2
|
||||||
@@ -242,7 +242,7 @@ func PointDistance(x1, y1, x2, y2 float64) float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsPrimes checks if number is prime number.
|
// IsPrimes checks if number is prime number.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/Rdd8UTHZJ7u
|
||||||
func IsPrime(n int) bool {
|
func IsPrime(n int) bool {
|
||||||
if n < 2 {
|
if n < 2 {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -492,6 +492,30 @@ func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initia
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReduceBy produces a value from slice by accumulating the result of each element as passed through the reducer function.
|
||||||
|
// Play: todo
|
||||||
|
func ReduceBy[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U {
|
||||||
|
accumulator := initial
|
||||||
|
|
||||||
|
for i, v := range slice {
|
||||||
|
accumulator = reducer(i, v, accumulator)
|
||||||
|
}
|
||||||
|
|
||||||
|
return accumulator
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReduceRight is like ReduceBy, but it iterates over elements of slice from right to left.
|
||||||
|
// Play: todo
|
||||||
|
func ReduceRight[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U {
|
||||||
|
accumulator := initial
|
||||||
|
|
||||||
|
for i := len(slice) - 1; i >= 0; i-- {
|
||||||
|
accumulator = reducer(i, slice[i], accumulator)
|
||||||
|
}
|
||||||
|
|
||||||
|
return accumulator
|
||||||
|
}
|
||||||
|
|
||||||
// Replace returns a copy of the slice with the first n non-overlapping instances of old replaced by new.
|
// Replace returns a copy of the slice with the first n non-overlapping instances of old replaced by new.
|
||||||
// Play: https://go.dev/play/p/P5mZp7IhOFo
|
// Play: https://go.dev/play/p/P5mZp7IhOFo
|
||||||
func Replace[T comparable](slice []T, old T, new T, n int) []T {
|
func Replace[T comparable](slice []T, old T, new T, n int) []T {
|
||||||
|
|||||||
@@ -460,6 +460,34 @@ func ExampleReduce() {
|
|||||||
// 6
|
// 6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleReduceBy() {
|
||||||
|
result1 := ReduceBy([]int{1, 2, 3, 4}, 0, func(_ int, item int, agg int) int {
|
||||||
|
return agg + item
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := ReduceBy([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 10
|
||||||
|
// 1234
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleReduceRight() {
|
||||||
|
result := ReduceRight([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 4321
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleReplace() {
|
func ExampleReplace() {
|
||||||
strs := []string{"a", "b", "c", "a"}
|
strs := []string{"a", "b", "c", "a"}
|
||||||
|
|
||||||
|
|||||||
@@ -405,6 +405,32 @@ func TestReduce(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReduceBy(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestReduceBy")
|
||||||
|
|
||||||
|
result1 := ReduceBy([]int{1, 2, 3, 4}, 0, func(_ int, item int, agg int) int {
|
||||||
|
return agg + item
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := ReduceBy([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(10, result1)
|
||||||
|
assert.Equal("1234", result2)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReduceRight(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "ReduceRight")
|
||||||
|
|
||||||
|
result := ReduceRight([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal("4321", result)
|
||||||
|
}
|
||||||
|
|
||||||
func TestIntSlice(t *testing.T) {
|
func TestIntSlice(t *testing.T) {
|
||||||
var nums []any
|
var nums []any
|
||||||
nums = append(nums, 1, 2, 3)
|
nums = append(nums, 1, 2, 3)
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
// Copyright 2023 dudaodong@gmail.com. All rights resulterved.
|
// Copyright 2023 dudaodong@gmail.com. All rights resulterved.
|
||||||
// Use of this source code is governed by MIT license
|
// Use of this source code is governed by MIT license
|
||||||
|
|
||||||
// Package stream implements a sequence of elements supporting sequential and parallel aggregate operations.
|
// Package stream implements a sequence of elements supporting sequential and operations.
|
||||||
// this package is an experiment to explore if stream in go can work as the way java does. it's complete, but not
|
// this package is an experiment to explore if stream in go can work as the way java does. it's function is very limited.
|
||||||
// powerful like other libs
|
|
||||||
package stream
|
package stream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -52,13 +51,14 @@ type stream[T any] struct {
|
|||||||
source []T
|
source []T
|
||||||
}
|
}
|
||||||
|
|
||||||
// Of creates a stream stream whose elements are the specified values.
|
// Of creates a stream whose elements are the specified values.
|
||||||
|
// Play: https://go.dev/play/p/jI6_iZZuVFE
|
||||||
func Of[T any](elems ...T) stream[T] {
|
func Of[T any](elems ...T) stream[T] {
|
||||||
return FromSlice(elems)
|
return FromSlice(elems)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate stream where each element is generated by the provided generater function
|
// Generate stream where each element is generated by the provided generater function
|
||||||
// generater function: func() func() (item T, ok bool) {}
|
// Play: https://go.dev/play/p/rkOWL1yA3j9
|
||||||
func Generate[T any](generator func() func() (item T, ok bool)) stream[T] {
|
func Generate[T any](generator func() func() (item T, ok bool)) stream[T] {
|
||||||
source := make([]T, 0)
|
source := make([]T, 0)
|
||||||
|
|
||||||
@@ -75,11 +75,13 @@ func Generate[T any](generator func() func() (item T, ok bool)) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FromSlice creates stream from slice.
|
// FromSlice creates stream from slice.
|
||||||
|
// Play: https://go.dev/play/p/wywTO0XZtI4
|
||||||
func FromSlice[T any](source []T) stream[T] {
|
func FromSlice[T any](source []T) stream[T] {
|
||||||
return stream[T]{source: source}
|
return stream[T]{source: source}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromChannel creates stream from channel.
|
// FromChannel creates stream from channel.
|
||||||
|
// Play: https://go.dev/play/p/9TZYugGMhXZ
|
||||||
func FromChannel[T any](source <-chan T) stream[T] {
|
func FromChannel[T any](source <-chan T) stream[T] {
|
||||||
s := make([]T, 0)
|
s := make([]T, 0)
|
||||||
|
|
||||||
@@ -91,6 +93,7 @@ func FromChannel[T any](source <-chan T) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FromRange creates 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]
|
||||||
|
// Play: https://go.dev/play/p/9Ex1-zcg-B-
|
||||||
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T] {
|
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T] {
|
||||||
if end < start {
|
if end < start {
|
||||||
panic("stream.FromRange: param start should be before param end")
|
panic("stream.FromRange: param start should be before param end")
|
||||||
@@ -109,6 +112,7 @@ func FromRange[T constraints.Integer | constraints.Float](start, end, step T) st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
// 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.
|
||||||
|
// Play: https://go.dev/play/p/HM4OlYk_OUC
|
||||||
func Concat[T any](a, b stream[T]) stream[T] {
|
func Concat[T any](a, b stream[T]) stream[T] {
|
||||||
source := make([]T, 0)
|
source := make([]T, 0)
|
||||||
|
|
||||||
@@ -119,6 +123,7 @@ func Concat[T any](a, b stream[T]) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Distinct returns a stream that removes the duplicated items.
|
// Distinct returns a stream that removes the duplicated items.
|
||||||
|
// Play: https://go.dev/play/p/eGkOSrm64cB
|
||||||
func (s stream[T]) Distinct() stream[T] {
|
func (s stream[T]) Distinct() stream[T] {
|
||||||
source := make([]T, 0)
|
source := make([]T, 0)
|
||||||
|
|
||||||
@@ -147,6 +152,7 @@ func hashKey(data any) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter returns a stream consisting of the elements of this stream that match the given predicate.
|
// Filter returns a stream consisting of the elements of this stream that match the given predicate.
|
||||||
|
// Play: https://go.dev/play/p/MFlSANo-buc
|
||||||
func (s stream[T]) Filter(predicate func(item T) bool) stream[T] {
|
func (s stream[T]) Filter(predicate func(item T) bool) stream[T] {
|
||||||
source := make([]T, 0)
|
source := make([]T, 0)
|
||||||
|
|
||||||
@@ -160,6 +166,7 @@ func (s stream[T]) Filter(predicate func(item T) bool) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Map returns a stream consisting of the elements of this stream that apply the given function to elements of stream.
|
// Map returns a stream consisting of the elements of this stream that apply the given function to elements of stream.
|
||||||
|
// Play: https://go.dev/play/p/OtNQUImdYko
|
||||||
func (s stream[T]) Map(mapper func(item T) T) stream[T] {
|
func (s stream[T]) Map(mapper func(item T) T) stream[T] {
|
||||||
source := make([]T, s.Count())
|
source := make([]T, s.Count())
|
||||||
|
|
||||||
@@ -171,6 +178,7 @@ func (s stream[T]) Map(mapper func(item T) T) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Peek returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
|
// Peek returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
|
||||||
|
// Play: https://go.dev/play/p/u1VNzHs6cb2
|
||||||
func (s stream[T]) Peek(consumer func(item T)) stream[T] {
|
func (s stream[T]) Peek(consumer func(item T)) stream[T] {
|
||||||
for _, v := range s.source {
|
for _, v := range s.source {
|
||||||
consumer(v)
|
consumer(v)
|
||||||
@@ -181,6 +189,7 @@ func (s stream[T]) Peek(consumer func(item T)) stream[T] {
|
|||||||
|
|
||||||
// Skip returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream.
|
// Skip returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream.
|
||||||
// If this stream contains fewer than n elements then an empty stream will be returned.
|
// If this stream contains fewer than n elements then an empty stream will be returned.
|
||||||
|
// Play: https://go.dev/play/p/fNdHbqjahum
|
||||||
func (s stream[T]) Skip(n int) stream[T] {
|
func (s stream[T]) Skip(n int) stream[T] {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
return s
|
return s
|
||||||
@@ -201,6 +210,7 @@ func (s stream[T]) Skip(n int) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Limit returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.
|
// Limit returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.
|
||||||
|
// Play: https://go.dev/play/p/qsO4aniDcGf
|
||||||
func (s stream[T]) Limit(maxSize int) stream[T] {
|
func (s stream[T]) Limit(maxSize int) stream[T] {
|
||||||
if s.source == nil {
|
if s.source == nil {
|
||||||
return s
|
return s
|
||||||
@@ -220,6 +230,7 @@ func (s stream[T]) Limit(maxSize int) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AllMatch returns whether all elements of this stream match the provided predicate.
|
// AllMatch returns whether all elements of this stream match the provided predicate.
|
||||||
|
// Play: https://go.dev/play/p/V5TBpVRs-Cx
|
||||||
func (s stream[T]) AllMatch(predicate func(item T) bool) bool {
|
func (s stream[T]) AllMatch(predicate func(item T) bool) bool {
|
||||||
for _, v := range s.source {
|
for _, v := range s.source {
|
||||||
if !predicate(v) {
|
if !predicate(v) {
|
||||||
@@ -231,6 +242,7 @@ func (s stream[T]) AllMatch(predicate func(item T) bool) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AnyMatch returns whether any elements of this stream match the provided predicate.
|
// AnyMatch returns whether any elements of this stream match the provided predicate.
|
||||||
|
// Play: https://go.dev/play/p/PTCnWn4OxSn
|
||||||
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool {
|
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool {
|
||||||
for _, v := range s.source {
|
for _, v := range s.source {
|
||||||
if predicate(v) {
|
if predicate(v) {
|
||||||
@@ -242,11 +254,13 @@ func (s stream[T]) AnyMatch(predicate func(item T) bool) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NoneMatch returns whether no elements of this stream match the provided predicate.
|
// NoneMatch returns whether no elements of this stream match the provided predicate.
|
||||||
|
// Play: https://go.dev/play/p/iWS64pL1oo3
|
||||||
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool {
|
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool {
|
||||||
return !s.AnyMatch(predicate)
|
return !s.AnyMatch(predicate)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForEach performs an action for each element of this stream.
|
// ForEach performs an action for each element of this stream.
|
||||||
|
// Play: https://go.dev/play/p/Dsm0fPqcidk
|
||||||
func (s stream[T]) ForEach(action func(item T)) {
|
func (s stream[T]) ForEach(action func(item T)) {
|
||||||
for _, v := range s.source {
|
for _, v := range s.source {
|
||||||
action(v)
|
action(v)
|
||||||
@@ -254,20 +268,23 @@ func (s stream[T]) ForEach(action func(item T)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reduce performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.
|
// Reduce performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.
|
||||||
func (s stream[T]) Reduce(init T, accumulator func(a, b T) T) T {
|
// Play: https://go.dev/play/p/6uzZjq_DJLU
|
||||||
|
func (s stream[T]) Reduce(initial T, accumulator func(a, b T) T) T {
|
||||||
for _, v := range s.source {
|
for _, v := range s.source {
|
||||||
init = accumulator(init, v)
|
initial = accumulator(initial, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
return init
|
return initial
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count returns the count of elements in the stream.
|
// Count returns the count of elements in the stream.
|
||||||
|
// Play: https://go.dev/play/p/r3koY6y_Xo-
|
||||||
func (s stream[T]) Count() int {
|
func (s stream[T]) Count() int {
|
||||||
return len(s.source)
|
return len(s.source)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindFirst returns the first element of this stream and true, or zero value and false if the stream is empty.
|
// FindFirst returns the first element of this stream and true, or zero value and false if the stream is empty.
|
||||||
|
// Play: https://go.dev/play/p/9xEf0-6C1e3
|
||||||
func (s stream[T]) FindFirst() (T, bool) {
|
func (s stream[T]) FindFirst() (T, bool) {
|
||||||
var result T
|
var result T
|
||||||
|
|
||||||
@@ -279,6 +296,7 @@ func (s stream[T]) FindFirst() (T, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reverse returns a stream whose elements are reverse order of given stream.
|
// Reverse returns a stream whose elements are reverse order of given stream.
|
||||||
|
// Play: https://go.dev/play/p/A8_zkJnLHm4
|
||||||
func (s stream[T]) Reverse() stream[T] {
|
func (s stream[T]) Reverse() stream[T] {
|
||||||
l := len(s.source)
|
l := len(s.source)
|
||||||
source := make([]T, l)
|
source := make([]T, l)
|
||||||
@@ -290,6 +308,7 @@ func (s stream[T]) Reverse() stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Range returns a stream whose elements are in the range from start(included) to end(excluded) original stream.
|
// Range returns a stream whose elements are in the range from start(included) to end(excluded) original stream.
|
||||||
|
// Play: https://go.dev/play/p/indZY5V2f4j
|
||||||
func (s stream[T]) Range(start, end int) stream[T] {
|
func (s stream[T]) Range(start, end int) stream[T] {
|
||||||
if start < 0 {
|
if start < 0 {
|
||||||
start = 0
|
start = 0
|
||||||
@@ -315,6 +334,7 @@ func (s stream[T]) Range(start, end int) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sorted returns a stream consisting of the elements of this stream, sorted according to the provided less function.
|
// Sorted returns a stream consisting of the elements of this stream, sorted according to the provided less function.
|
||||||
|
// Play: https://go.dev/play/p/XXtng5uonFj
|
||||||
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T] {
|
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T] {
|
||||||
source := []T{}
|
source := []T{}
|
||||||
source = append(source, s.source...)
|
source = append(source, s.source...)
|
||||||
@@ -326,6 +346,7 @@ func (s stream[T]) Sorted(less func(a, b T) bool) stream[T] {
|
|||||||
|
|
||||||
// Max returns the maximum element of this stream according to the provided less function.
|
// Max returns the maximum element of this stream according to the provided less function.
|
||||||
// less: a > b
|
// less: a > b
|
||||||
|
// Play: https://go.dev/play/p/fm-1KOPtGzn
|
||||||
func (s stream[T]) Max(less func(a, b T) bool) (T, bool) {
|
func (s stream[T]) Max(less func(a, b T) bool) (T, bool) {
|
||||||
var max T
|
var max T
|
||||||
|
|
||||||
@@ -343,6 +364,7 @@ func (s stream[T]) Max(less func(a, b T) bool) (T, bool) {
|
|||||||
|
|
||||||
// Min returns the minimum element of this stream according to the provided less function.
|
// Min returns the minimum element of this stream according to the provided less function.
|
||||||
// less: a < b
|
// less: a < b
|
||||||
|
// Play: https://go.dev/play/p/vZfIDgGNRe_0
|
||||||
func (s stream[T]) Min(less func(a, b T) bool) (T, bool) {
|
func (s stream[T]) Min(less func(a, b T) bool) (T, bool) {
|
||||||
var min T
|
var min T
|
||||||
|
|
||||||
@@ -360,6 +382,7 @@ func (s stream[T]) Min(less func(a, b T) bool) (T, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ToSlice return the elements in the stream.
|
// ToSlice return the elements in the stream.
|
||||||
|
// Play: https://go.dev/play/p/jI6_iZZuVFE
|
||||||
func (s stream[T]) ToSlice() []T {
|
func (s stream[T]) ToSlice() []T {
|
||||||
return s.source
|
return s.source
|
||||||
}
|
}
|
||||||
|
|||||||
373
stream/stream_example_test.go
Normal file
373
stream/stream_example_test.go
Normal file
@@ -0,0 +1,373 @@
|
|||||||
|
package stream
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleOf() {
|
||||||
|
s := Of(1, 2, 3)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleFromSlice() {
|
||||||
|
s := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleFromChannel() {
|
||||||
|
ch := make(chan int)
|
||||||
|
go func() {
|
||||||
|
for i := 1; i < 4; i++ {
|
||||||
|
ch <- i
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
}()
|
||||||
|
|
||||||
|
s := FromChannel(ch)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleFromRange() {
|
||||||
|
s := FromRange(1, 5, 1)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4 5]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleGenerate() {
|
||||||
|
n := 0
|
||||||
|
max := 4
|
||||||
|
|
||||||
|
generator := func() func() (int, bool) {
|
||||||
|
return func() (int, bool) {
|
||||||
|
n++
|
||||||
|
return n, n < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s := Generate(generator)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleConcat() {
|
||||||
|
s1 := FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := FromSlice([]int{4, 5, 6})
|
||||||
|
|
||||||
|
s := Concat(s1, s2)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4 5 6]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Distinct() {
|
||||||
|
original := FromSlice([]int{1, 2, 2, 3, 3, 3})
|
||||||
|
distinct := original.Distinct()
|
||||||
|
|
||||||
|
data1 := original.ToSlice()
|
||||||
|
data2 := distinct.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data1)
|
||||||
|
fmt.Println(data2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 2 3 3 3]
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Filter() {
|
||||||
|
original := FromSlice([]int{1, 2, 3, 4, 5})
|
||||||
|
|
||||||
|
isEven := func(n int) bool {
|
||||||
|
return n%2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
even := original.Filter(isEven)
|
||||||
|
|
||||||
|
fmt.Println(even.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Map() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
addOne := func(n int) int {
|
||||||
|
return n + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
increament := original.Map(addOne)
|
||||||
|
|
||||||
|
fmt.Println(increament.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 3 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Peek() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
data := []string{}
|
||||||
|
peekStream := original.Peek(func(n int) {
|
||||||
|
data = append(data, fmt.Sprint("value", n))
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(original.ToSlice())
|
||||||
|
fmt.Println(peekStream.ToSlice())
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
// [1 2 3]
|
||||||
|
// [value1 value2 value3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Skip() {
|
||||||
|
original := FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
|
s1 := original.Skip(-1)
|
||||||
|
s2 := original.Skip(0)
|
||||||
|
s3 := original.Skip(1)
|
||||||
|
s4 := original.Skip(5)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [2 3 4]
|
||||||
|
// []
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Limit() {
|
||||||
|
original := FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
|
s1 := original.Limit(-1)
|
||||||
|
s2 := original.Limit(0)
|
||||||
|
s3 := original.Limit(1)
|
||||||
|
s4 := original.Limit(5)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []
|
||||||
|
// []
|
||||||
|
// [1]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_AllMatch() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.AllMatch(func(item int) bool {
|
||||||
|
return item > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.AllMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_AnyMatch() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.AnyMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.AnyMatch(func(item int) bool {
|
||||||
|
return item > 3
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_NoneMatch() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.NoneMatch(func(item int) bool {
|
||||||
|
return item > 3
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.NoneMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_ForEach() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result := 0
|
||||||
|
original.ForEach(func(item int) {
|
||||||
|
result += item
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 6
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Reduce() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result := original.Reduce(0, func(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 6
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_FindFirst() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result, ok := original.FindFirst()
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Reverse() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
reverse := original.Reverse()
|
||||||
|
|
||||||
|
fmt.Println(reverse.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [3 2 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Range() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
s1 := original.Range(0, 0)
|
||||||
|
s2 := original.Range(0, 1)
|
||||||
|
s3 := original.Range(0, 3)
|
||||||
|
s4 := original.Range(1, 2)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []
|
||||||
|
// [1]
|
||||||
|
// [1 2 3]
|
||||||
|
// [2]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Sorted() {
|
||||||
|
original := FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
sorted := original.Sorted(func(a, b int) bool { return a < b })
|
||||||
|
|
||||||
|
fmt.Println(original.ToSlice())
|
||||||
|
fmt.Println(sorted.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [4 2 1 3]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Max() {
|
||||||
|
original := FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
max, ok := original.Max(func(a, b int) bool { return a > b })
|
||||||
|
|
||||||
|
fmt.Println(max)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 4
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Min() {
|
||||||
|
original := FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
min, ok := original.Min(func(a, b int) bool { return a < b })
|
||||||
|
|
||||||
|
fmt.Println(min)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Count() {
|
||||||
|
s1 := FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := FromSlice([]int{})
|
||||||
|
|
||||||
|
fmt.Println(s1.Count())
|
||||||
|
fmt.Println(s2.Count())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 3
|
||||||
|
// 0
|
||||||
|
}
|
||||||
@@ -147,13 +147,17 @@ func TestStream_Peek(t *testing.T) {
|
|||||||
func TestStream_Skip(t *testing.T) {
|
func TestStream_Skip(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestStream_Peek")
|
assert := internal.NewAssert(t, "TestStream_Peek")
|
||||||
|
|
||||||
stream := FromSlice([]int{1, 2, 3, 4, 5, 6})
|
stream := FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
s1 := stream.Skip(-1)
|
s1 := stream.Skip(-1)
|
||||||
s2 := stream.Skip(0)
|
s2 := stream.Skip(0)
|
||||||
|
s3 := stream.Skip(1)
|
||||||
|
s4 := stream.Skip(2)
|
||||||
|
|
||||||
assert.Equal([]int{1, 2, 3, 4, 5, 6}, s1.ToSlice())
|
assert.Equal([]int{1, 2, 3, 4}, s1.ToSlice())
|
||||||
assert.Equal([]int{1, 2, 3, 4, 5, 6}, s2.ToSlice())
|
assert.Equal([]int{1, 2, 3, 4}, s2.ToSlice())
|
||||||
|
assert.Equal([]int{2, 3, 4}, s3.ToSlice())
|
||||||
|
assert.Equal([]int{3, 4}, s4.ToSlice())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStream_Limit(t *testing.T) {
|
func TestStream_Limit(t *testing.T) {
|
||||||
@@ -248,6 +252,16 @@ func TestStream_Reduce(t *testing.T) {
|
|||||||
assert.Equal(6, result)
|
assert.Equal(6, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStream_Count(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestStream_Count")
|
||||||
|
|
||||||
|
s1 := FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := FromSlice([]int{})
|
||||||
|
|
||||||
|
assert.Equal(3, s1.Count())
|
||||||
|
assert.Equal(0, s2.Count())
|
||||||
|
}
|
||||||
|
|
||||||
func TestStream_FindFirst(t *testing.T) {
|
func TestStream_FindFirst(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestStream_FindFirst")
|
assert := internal.NewAssert(t, "TestStream_FindFirst")
|
||||||
|
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ func WordCount(s string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RemoveNonPrintable remove non-printable characters from a string.
|
// RemoveNonPrintable remove non-printable characters from a string.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/og47F5x_jTZ
|
||||||
func RemoveNonPrintable(str string) string {
|
func RemoveNonPrintable(str string) string {
|
||||||
result := strings.Map(func(r rune) rune {
|
result := strings.Map(func(r rune) rune {
|
||||||
if unicode.IsPrint(r) {
|
if unicode.IsPrint(r) {
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ func IsAllLower(str string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsASCII checks if string is all ASCII char.
|
// IsASCII checks if string is all ASCII char.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/hfQNPLX0jNa
|
||||||
func IsASCII(str string) bool {
|
func IsASCII(str string) bool {
|
||||||
for i := 0; i < len(str); i++ {
|
for i := 0; i < len(str); i++ {
|
||||||
if str[i] > unicode.MaxASCII {
|
if str[i] > unicode.MaxASCII {
|
||||||
@@ -70,7 +70,7 @@ func IsASCII(str string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsPrintable checks if string is all printable chars.
|
// IsPrintable checks if string is all printable chars.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/Pe1FE2gdtTP
|
||||||
func IsPrintable(str string) bool {
|
func IsPrintable(str string) bool {
|
||||||
for _, r := range str {
|
for _, r := range str {
|
||||||
if !unicode.IsPrint(r) {
|
if !unicode.IsPrint(r) {
|
||||||
@@ -369,3 +369,29 @@ func IsGBK(data []byte) bool {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsNumberStr check if the value is Number(integer, float) or not.
|
||||||
|
// Play: todo
|
||||||
|
func IsNumber(v any) bool {
|
||||||
|
return IsInt(v) || IsFloat(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFloat check if the value is float(float32, float34) or not.
|
||||||
|
// Play: todo
|
||||||
|
func IsFloat(v any) bool {
|
||||||
|
switch v.(type) {
|
||||||
|
case float32, float64:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsInt check if the value is integer(int, unit) or not.
|
||||||
|
// Play: todo
|
||||||
|
func IsInt(v any) bool {
|
||||||
|
switch v.(type) {
|
||||||
|
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -449,3 +449,57 @@ func ExampleIsPrintable() {
|
|||||||
// true
|
// true
|
||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleIsInt() {
|
||||||
|
result1 := IsInt("")
|
||||||
|
result2 := IsInt("3")
|
||||||
|
result3 := IsInt(0.1)
|
||||||
|
result4 := IsInt(0)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleIsFloat() {
|
||||||
|
result1 := IsFloat("")
|
||||||
|
result2 := IsFloat("3")
|
||||||
|
result3 := IsFloat(0)
|
||||||
|
result4 := IsFloat(0.1)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleIsNumber() {
|
||||||
|
result1 := IsNumber("")
|
||||||
|
result2 := IsNumber("3")
|
||||||
|
result3 := IsNumber(0)
|
||||||
|
result4 := IsNumber(0.1)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|||||||
@@ -100,6 +100,34 @@ func TestIsJSON(t *testing.T) {
|
|||||||
assert.Equal(false, IsJSON("&@#$%^&*"))
|
assert.Equal(false, IsJSON("&@#$%^&*"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsNumber(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsNumber")
|
||||||
|
|
||||||
|
assert.Equal(false, IsNumber(""))
|
||||||
|
assert.Equal(false, IsNumber("3"))
|
||||||
|
assert.Equal(true, IsNumber(0))
|
||||||
|
assert.Equal(true, IsNumber(0.1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsFloat(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsFloat")
|
||||||
|
|
||||||
|
assert.Equal(false, IsFloat(""))
|
||||||
|
assert.Equal(false, IsFloat("3"))
|
||||||
|
assert.Equal(false, IsFloat(0))
|
||||||
|
assert.Equal(true, IsFloat(0.1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsInt(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsInt")
|
||||||
|
|
||||||
|
assert.Equal(false, IsInt(""))
|
||||||
|
assert.Equal(false, IsInt("3"))
|
||||||
|
assert.Equal(false, IsInt(0.1))
|
||||||
|
assert.Equal(true, IsInt(0))
|
||||||
|
assert.Equal(true, IsInt(-1))
|
||||||
|
}
|
||||||
|
|
||||||
func TestIsNumberStr(t *testing.T) {
|
func TestIsNumberStr(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestIsNumberStr")
|
assert := internal.NewAssert(t, "TestIsNumberStr")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user