mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-17 19:22:28 +08:00
Compare commits
42 Commits
v2.1.15
...
ef1e548dfc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef1e548dfc | ||
|
|
924589d2da | ||
|
|
77f32f4cc6 | ||
|
|
1755dd249b | ||
|
|
7a25688ec1 | ||
|
|
51a6912eb3 | ||
|
|
28d0428b50 | ||
|
|
6a9eb645bb | ||
|
|
3857b342f6 | ||
|
|
71aa91a58d | ||
|
|
081908bce3 | ||
|
|
66efe61834 | ||
|
|
94f7f3e0e5 | ||
|
|
9d2c9806d1 | ||
|
|
e523d4af6e | ||
|
|
f3801bcd8f | ||
|
|
5767aad303 | ||
|
|
f7aaa1ed2a | ||
|
|
ef19a414bc | ||
|
|
65704dea06 | ||
|
|
5eac358bb0 | ||
|
|
8e36ef5cef | ||
|
|
21b0d2ec0e | ||
|
|
32ca975204 | ||
|
|
ec740e442c | ||
|
|
ed98ad53ec | ||
|
|
af7b9d2710 | ||
|
|
f08b368001 | ||
|
|
be8a0558f8 | ||
|
|
46de539e22 | ||
|
|
36fb3abe9e | ||
|
|
fee8d325b7 | ||
|
|
8784be1583 | ||
|
|
84cd68de7f | ||
|
|
a774c060ce | ||
|
|
730f061b95 | ||
|
|
2eb08f3404 | ||
|
|
4c1496b648 | ||
|
|
c2ae784f27 | ||
|
|
e71cecefea | ||
|
|
572e53aa14 | ||
|
|
ca9ecb9c8a |
97
README.md
97
README.md
@@ -4,7 +4,7 @@
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/duke-git/lancet/releases)
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
@@ -38,10 +38,10 @@ English | [简体中文](./README_zh-CN.md)
|
|||||||
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
|
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
|
||||||
```
|
```
|
||||||
|
|
||||||
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.3.6. </b>
|
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.3.7. </b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
go get github.com/duke-git/lancet@v1.3.6 // below go1.18, install latest version of v1.x.x
|
go get github.com/duke-git/lancet@v1.3.7 // below go1.18, install latest version of v1.x.x
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -248,6 +248,10 @@ import "github.com/duke-git/lancet/v2/convertor"
|
|||||||
[[play](https://go.dev/play/p/zI6xsmuQRbn)]
|
[[play](https://go.dev/play/p/zI6xsmuQRbn)]
|
||||||
- **<big>DeepClone</big>** : creates a deep copy of passed item, can't clone unexported field of struct.
|
- **<big>DeepClone</big>** : creates a deep copy of passed item, can't clone unexported field of struct.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#DeepClone)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#DeepClone)]
|
||||||
|
[[play](https://go.dev/play/p/j4DP5dquxnk)]
|
||||||
|
- **<big>CopyProperties</big>** : copies each field from the source struct into the destination struct.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#CopyProperties)]
|
||||||
|
[[play](https://go.dev/play/p/FOVY3XJL-6B)]
|
||||||
|
|
||||||
### 5. Cryptor package is for data encryption and decryption.
|
### 5. Cryptor package is for data encryption and decryption.
|
||||||
|
|
||||||
@@ -452,9 +456,6 @@ import "github.com/duke-git/lancet/v2/datetime"
|
|||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)]
|
||||||
[[play](https://go.dev/play/p/mkhOHQkdeA2)]
|
[[play](https://go.dev/play/p/mkhOHQkdeA2)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 7. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph.
|
### 7. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -589,7 +590,6 @@ import "github.com/duke-git/lancet/v2/function"
|
|||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)]
|
||||||
[[play](https://go.dev/play/p/l2yrOpCLd1I)]
|
[[play](https://go.dev/play/p/l2yrOpCLd1I)]
|
||||||
|
|
||||||
|
|
||||||
### 11. Maputil package includes some functions to manipulate map.
|
### 11. Maputil package includes some functions to manipulate map.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -604,12 +604,30 @@ import "github.com/duke-git/lancet/v2/maputil"
|
|||||||
- **<big>Filter</big>** : iterates over map, return a new map contains all key and value pairs pass the predicate function.
|
- **<big>Filter</big>** : iterates over map, return a new map contains all key and value pairs pass the predicate function.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Filter)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Filter)]
|
||||||
[[play](https://go.dev/play/p/fSvF3wxuNG7)]
|
[[play](https://go.dev/play/p/fSvF3wxuNG7)]
|
||||||
|
- **<big>FilterByKeys</big>** : iterates over map, return a new map whose keys are all given keys
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#FilterByKeys)]
|
||||||
|
[[play](https://go.dev/play/p/7ov6BJHbVqh)]
|
||||||
|
- **<big>FilterByValues</big>** : iterates over map, return a new map whose values are all given values.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#FilterByValues)]
|
||||||
|
[[play](https://go.dev/play/p/P3-9MdcXegR)]
|
||||||
|
- **<big>OmitBy</big>** : the opposite of Filter, removes all the map elements for which the predicate function returns true.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#OmitBy)]
|
||||||
|
[[play](https://go.dev/play/p/YJM4Hj5hNwm)]
|
||||||
|
- **<big>OmitByKeys</big>** : the opposite of FilterByKeys, extracts all the map elements which keys are not omitted.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#OmitByKeys)]
|
||||||
|
[[play](https://go.dev/play/p/jXGrWDBfSRp)]
|
||||||
|
- **<big>OmitByValues</big>** : the opposite of FilterByValues. remov all elements whose value are in the give slice.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#OmitByValues)]
|
||||||
|
[[play](https://go.dev/play/p/XB7Y10uw20_U)]
|
||||||
- **<big>Intersect</big>** : iterates over maps, return a new map of key and value pairs in all given maps.
|
- **<big>Intersect</big>** : iterates over maps, return a new map of key and value pairs in all given maps.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Intersect)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Intersect)]
|
||||||
[[play](https://go.dev/play/p/Zld0oj3sjcC)]
|
[[play](https://go.dev/play/p/Zld0oj3sjcC)]
|
||||||
- **<big>Keys</big>** : returns a slice of the map's keys.
|
- **<big>Keys</big>** : returns a slice of the map's keys.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Keys)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Keys)]
|
||||||
[[play](https://go.dev/play/p/xNB5bTb97Wd)]
|
[[play](https://go.dev/play/p/xNB5bTb97Wd)]
|
||||||
|
- **<big>KeysBy</big>** : creates a slice whose element is the result of function mapper invoked by every map's key.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#KeysBy)]
|
||||||
|
[[play](https://go.dev/play/p/hI371iB8Up8)]
|
||||||
- **<big>Merge</big>** : merge maps, next key will overwrite previous key.
|
- **<big>Merge</big>** : merge maps, next key will overwrite previous key.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Merge)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Merge)]
|
||||||
[[play](https://go.dev/play/p/H95LENF1uB-)]
|
[[play](https://go.dev/play/p/H95LENF1uB-)]
|
||||||
@@ -619,6 +637,24 @@ import "github.com/duke-git/lancet/v2/maputil"
|
|||||||
- **<big>Values</big>** : returns a slice of the map's values.
|
- **<big>Values</big>** : returns a slice of the map's values.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Values)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Values)]
|
||||||
[[play](https://go.dev/play/p/CBKdUc5FTW6)]
|
[[play](https://go.dev/play/p/CBKdUc5FTW6)]
|
||||||
|
- **<big>ValuesBy</big>** : creates a slice whose element is the result of function mapper invoked by every map's value.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ValuesBy)]
|
||||||
|
[[play](https://go.dev/play/p/sg9-oRidh8f)]
|
||||||
|
- **<big>MapKeys</big>** : transforms a map to other type map by manipulating it's keys.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#MapKeys)]
|
||||||
|
[[play](https://go.dev/play/p/8scDxWeBDKd)]
|
||||||
|
- **<big>MapValues</big>** : transforms a map to other type map by manipulating it's values.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#MapValues)]
|
||||||
|
[[play](https://go.dev/play/p/g92aY3fc7Iw)]
|
||||||
|
- **<big>Entries</big>** : transforms a map into array of key/value pairs.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Entries)]
|
||||||
|
[[play](https://go.dev/play/p/Ltb11LNcElY)]
|
||||||
|
- **<big>FromEntries</big>** : creates a map based on a slice of key/value pairs.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#FromEntries)]
|
||||||
|
[[play](https://go.dev/play/p/fTdu4sCNjQO)]
|
||||||
|
- **<big>Transform</big>** : transform a map to another type map.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Transform)]
|
||||||
|
[[play](https://go.dev/play/p/P6ovfToM3zj)]
|
||||||
- **<big>IsDisjoint</big>** : check two map are disjoint if they have no keys in common.
|
- **<big>IsDisjoint</big>** : check two map are disjoint if they have no keys in common.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#IsDisjoint)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#IsDisjoint)]
|
||||||
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
|
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
|
||||||
@@ -731,8 +767,6 @@ import "github.com/duke-git/lancet/v2/netutil"
|
|||||||
- **<big>ParseHttpResponse</big>** : decode http response into target object.
|
- **<big>ParseHttpResponse</big>** : decode http response into target object.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 14. Random package implements some basic functions to generate random int and string.
|
### 14. Random package implements some basic functions to generate random int and string.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -804,6 +838,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
- **<big>Contain</big>** : check if the value is in the slice or not.
|
- **<big>Contain</big>** : check if the value is in the slice or not.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Contain)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Contain)]
|
||||||
[[play](https://go.dev/play/p/_454yEHcNjf)]
|
[[play](https://go.dev/play/p/_454yEHcNjf)]
|
||||||
|
- **<big>ContainBy</big>** : returns true if predicate function return true.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainBy)]
|
||||||
|
[[play](https://go.dev/play/p/49tkHfX4GNc)]
|
||||||
- **<big>ContainSubSlice</big>** : check if the slice contain a given subslice or not.
|
- **<big>ContainSubSlice</big>** : check if the slice contain a given subslice or not.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainSubSlice)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainSubSlice)]
|
||||||
[[play](https://go.dev/play/p/bcuQ3UT6Sev)]
|
[[play](https://go.dev/play/p/bcuQ3UT6Sev)]
|
||||||
@@ -836,13 +873,16 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
|
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
|
||||||
- **<big>Drop</big>** : drop n elements from the start of a slice.
|
- **<big>Drop</big>** : drop n elements from the start of a slice.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)]
|
||||||
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
|
[[play](https://go.dev/play/p/jnPO2yQsT8H)]
|
||||||
- **<big>DropRight</big>** : drop n elements from the end of a slice.
|
- **<big>DropRight</big>** : drop n elements from the end of a slice.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DropRight)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DropRight)]
|
||||||
|
[[play](https://go.dev/play/p/8bcXvywZezG)]
|
||||||
- **<big>DropWhile</big>** : drop n elements from the start of a slice while predicate function returns true.
|
- **<big>DropWhile</big>** : drop n elements from the start of a slice while predicate function returns true.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DropWhile)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DropWhile)]
|
||||||
|
[[play](https://go.dev/play/p/4rt252UV_qs)]
|
||||||
- **<big>DropRightWhile</big>** : drop n elements from the end of a slice while predicate function returns true.
|
- **<big>DropRightWhile</big>** : drop n elements from the end of a slice while predicate function returns true.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DropRightWhile)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DropRightWhile)]
|
||||||
|
[[play](https://go.dev/play/p/6wyK3zMY56e)]
|
||||||
- **<big>Equal</big>** : checks if two slices are equal: the same length and all elements' order and value are equal.
|
- **<big>Equal</big>** : checks if two slices are equal: the same length and all elements' order and value are equal.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Equal)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Equal)]
|
||||||
[[play](https://go.dev/play/p/WcRQJ37ifPa)]
|
[[play](https://go.dev/play/p/WcRQJ37ifPa)]
|
||||||
@@ -855,6 +895,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
- **<big>Filter</big>** : iterates over elements of slice, returning an slice of all elements pass the predicate function.
|
- **<big>Filter</big>** : iterates over elements of slice, returning an slice of all elements pass the predicate function.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)]
|
||||||
[[play](https://go.dev/play/p/SdPna-7qK4T)]
|
[[play](https://go.dev/play/p/SdPna-7qK4T)]
|
||||||
|
- **<big>FilterMap</big>** : returns a slice which apply both filtering and mapping to the given slice.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FilterMap)]
|
||||||
|
[[play](https://go.dev/play/p/J94SZ_9MiIe)]
|
||||||
- **<big>Find</big>** : iterates over elements of slice, returning the first one that passes a truth test on predicate function.
|
- **<big>Find</big>** : iterates over elements of slice, returning the first one that passes a truth test on predicate function.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Find)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Find)]
|
||||||
[[play](https://go.dev/play/p/CBKeBoHVLgq)]
|
[[play](https://go.dev/play/p/CBKeBoHVLgq)]
|
||||||
@@ -867,6 +910,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
- **<big>FlattenDeep</big>** : flattens slice recursive to one level.
|
- **<big>FlattenDeep</big>** : flattens slice recursive to one level.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlattenDeep)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlattenDeep)]
|
||||||
[[play](https://go.dev/play/p/yjYNHPyCFaF)]
|
[[play](https://go.dev/play/p/yjYNHPyCFaF)]
|
||||||
|
- **<big>FlatMap</big>** : manipulates a slice and transforms and flattens it to a slice of another type.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlatMap)]
|
||||||
|
[[play](https://go.dev/play/p/_QARWlWs1N_F)]
|
||||||
- **<big>ForEach</big>** : iterates over elements of slice and invokes function for each element.
|
- **<big>ForEach</big>** : iterates over elements of slice and invokes function for each element.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)]
|
||||||
[[play](https://go.dev/play/p/DrPaa4YsHRF)]
|
[[play](https://go.dev/play/p/DrPaa4YsHRF)]
|
||||||
@@ -920,12 +966,16 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
[[play](https://go.dev/play/p/YHvhnWGU3Ge)]
|
[[play](https://go.dev/play/p/YHvhnWGU3Ge)]
|
||||||
- **<big>IsAscending</big>** : Checks if a slice is ascending order.
|
- **<big>IsAscending</big>** : Checks if a slice is ascending order.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsAscending)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsAscending)]
|
||||||
|
[[play](https://go.dev/play/p/9CtsFjet4SH)]
|
||||||
- **<big>IsDescending</big>** : Checks if a slice is descending order.
|
- **<big>IsDescending</big>** : Checks if a slice is descending order.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsDescending)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsDescending)]
|
||||||
|
[[play](https://go.dev/play/p/U_LljFXma14)]
|
||||||
- **<big>IsSorted</big>** : Checks if a slice is sorted (ascending or descending).
|
- **<big>IsSorted</big>** : Checks if a slice is sorted (ascending or descending).
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsSorted)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsSorted)]
|
||||||
|
[[play](https://go.dev/play/p/nCE8wPLwSA-)]
|
||||||
- **<big>IsSortedByKey</big>** : Checks if a slice is sorted by iteratee function.
|
- **<big>IsSortedByKey</big>** : Checks if a slice is sorted by iteratee function.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsSortedByKey)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsSortedByKey)]
|
||||||
|
[[play](https://go.dev/play/p/tUoGB7DOHI4)]
|
||||||
- **<big>Sort</big>** : sorts a slice of any ordered type(number or string).
|
- **<big>Sort</big>** : sorts a slice of any ordered type(number or string).
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Sort)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Sort)]
|
||||||
[[play](https://go.dev/play/p/V9AVjzf_4Fk)]
|
[[play](https://go.dev/play/p/V9AVjzf_4Fk)]
|
||||||
@@ -1012,6 +1062,9 @@ import "github.com/duke-git/lancet/v2/strutil"
|
|||||||
- **<big>UpperFirst</big>** : converts the first character of string to upper case.
|
- **<big>UpperFirst</big>** : converts the first character of string to upper case.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperFirst)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperFirst)]
|
||||||
[[play](https://go.dev/play/p/sBbBxRbs8MM)]
|
[[play](https://go.dev/play/p/sBbBxRbs8MM)]
|
||||||
|
- **<big>Pad</big>** : pads string on the left and right side if it's shorter than size.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Pad)]
|
||||||
|
[[play](https://go.dev/play/p/NzImQq-VF8q)]
|
||||||
- **<big>PadEnd</big>** : pads string with given characters on the right side if it's shorter than limit size. Padding characters are truncated if they exceed size.
|
- **<big>PadEnd</big>** : pads string with given characters on the right side if it's shorter than limit size. Padding characters are truncated if they exceed size.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadEnd)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadEnd)]
|
||||||
[[play](https://go.dev/play/p/9xP8rN0vz--)]
|
[[play](https://go.dev/play/p/9xP8rN0vz--)]
|
||||||
@@ -1039,6 +1092,12 @@ import "github.com/duke-git/lancet/v2/strutil"
|
|||||||
- **<big>Unwrap</big>** : unwrap a given string from anther string. will change source string.
|
- **<big>Unwrap</big>** : unwrap a given string from anther string. will change source string.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap)]
|
||||||
[[play](https://go.dev/play/p/Ec2q4BzCpG-)]
|
[[play](https://go.dev/play/p/Ec2q4BzCpG-)]
|
||||||
|
- **<big>SplitWords</big>** : splits a string into words, word only contains alphabetic characters.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitWords)]
|
||||||
|
[[play](https://go.dev/play/p/KLiX4WiysMM)]
|
||||||
|
- **<big>WordCount</big>** : return the number of meaningful word of a string, word only contains alphabetic characters.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#WordCount)]
|
||||||
|
[[play](https://go.dev/play/p/bj7_odx3vRf)]
|
||||||
|
|
||||||
### 19. System package contain some functions about os, runtime, shell command.
|
### 19. System package contain some functions about os, runtime, shell command.
|
||||||
|
|
||||||
@@ -1176,34 +1235,46 @@ import "github.com/duke-git/lancet/v2/xerror"
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### Function list:
|
||||||
|
|
||||||
- **<big>New</big>** : creates a new XError pointer instance with message.
|
- **<big>New</big>** : creates a new XError pointer instance with message.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#New)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#New)]
|
||||||
|
[[play](https://go.dev/play/p/w4oWZts7q7f)]
|
||||||
- **<big>Wrap</big>** : creates a new XError pointer instance based on error object, and add message.
|
- **<big>Wrap</big>** : creates a new XError pointer instance based on error object, and add message.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Wrap)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Wrap)]
|
||||||
|
[[play](https://go.dev/play/p/5385qT2dCi4)]
|
||||||
- **<big>Unwrap</big>** : returns unwrapped XError from err by errors.As. If no XError, returns nil.
|
- **<big>Unwrap</big>** : returns unwrapped XError from err by errors.As. If no XError, returns nil.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Unwrap)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Unwrap)]
|
||||||
|
[[play](https://go.dev/play/p/LKMLep723tu)]
|
||||||
- **<big>XError_Wrap</big>** : creates a new XError and copy message and id to new one.
|
- **<big>XError_Wrap</big>** : creates a new XError and copy message and id to new one.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Wrap)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Wrap)]
|
||||||
|
[[play](https://go.dev/play/p/5385qT2dCi4)]
|
||||||
- **<big>XError_Unwrap</big>** : Compatible with github.com/pkg/errors.
|
- **<big>XError_Unwrap</big>** : Compatible with github.com/pkg/errors.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Unwrap)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Unwrap)]
|
||||||
|
[[play](https://go.dev/play/p/VUXJ8BST4c6)]
|
||||||
- **<big>XError_With</big>** : adds key and value related to the XError object.
|
- **<big>XError_With</big>** : adds key and value related to the XError object.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_With)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_With)]
|
||||||
|
[[play](https://go.dev/play/p/ow8UISXX_Dp)]
|
||||||
- **<big>XError_Id</big>** : sets XError object id to check equality in XError.Is.
|
- **<big>XError_Id</big>** : sets XError object id to check equality in XError.Is.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Id)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Id)]
|
||||||
|
[[play](https://go.dev/play/p/X6HBlsy58U9)]
|
||||||
- **<big>XError_Is</big>** : checks if target error is XError and Error.id of two errors are matched.
|
- **<big>XError_Is</big>** : checks if target error is XError and Error.id of two errors are matched.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Is)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Is)]
|
||||||
- **<big>XError_Values</big>** : returns map of key and value that is set by XError.With function.
|
[[play](https://go.dev/play/p/X6HBlsy58U9)]
|
||||||
|
- **<big>XError_Values</big>** : returns map of key and value that is set by XError.With function.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Values)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Values)]
|
||||||
|
[[play](https://go.dev/play/p/ow8UISXX_Dp)]
|
||||||
- **<big>XError_StackTrace</big>** : returns stack trace which is compatible with pkg/errors.
|
- **<big>XError_StackTrace</big>** : returns stack trace which is compatible with pkg/errors.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_StackTrace)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_StackTrace)]
|
||||||
|
[[play](https://go.dev/play/p/6FAvSQpa7pc)]
|
||||||
- **<big>XError_Info</big>** : returns information of xerror, which can be printed.
|
- **<big>XError_Info</big>** : returns information of xerror, which can be printed.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Info)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Info)]
|
||||||
|
[[play](https://go.dev/play/p/1ZX0ME1F-Jb)]
|
||||||
- **<big>XError_Error</big>** : implements standard error interface.
|
- **<big>XError_Error</big>** : implements standard error interface.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Error)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Error)]
|
||||||
|
[[play](https://go.dev/play/p/w4oWZts7q7f)]
|
||||||
- **<big>TryUnwrap</big>** : check if err is nil then it returns a valid value. If err is not nil, TryUnwrap panics with err.
|
- **<big>TryUnwrap</big>** : check if err is nil then it returns a valid value. If err is not nil, TryUnwrap panics with err.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#TryUnwrap)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#TryUnwrap)]
|
||||||
[[play](https://go.dev/play/p/w84d7Mb3Afk)]
|
[[play](https://go.dev/play/p/acyZVkNZEeW)]
|
||||||
|
|
||||||
|
|
||||||
## How to Contribute
|
## How to Contribute
|
||||||
|
|
||||||
|
|||||||
360
README_zh-CN.md
360
README_zh-CN.md
@@ -4,7 +4,7 @@
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/duke-git/lancet/releases)
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
@@ -37,10 +37,10 @@
|
|||||||
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
|
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
|
||||||
```
|
```
|
||||||
|
|
||||||
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.3.6。</b>
|
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.3.7。</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
go get github.com/duke-git/lancet@v1.3.6 // 使用go1.18以下版本, 必须安装v1.x.x版本
|
go get github.com/duke-git/lancet@v1.3.7 // 使用go1.18以下版本, 必须安装v1.x.x版本
|
||||||
```
|
```
|
||||||
|
|
||||||
## 用法
|
## 用法
|
||||||
@@ -181,7 +181,7 @@ import "github.com/duke-git/lancet/v2/condition"
|
|||||||
[[play](https://go.dev/play/p/g2j08F_zZky)
|
[[play](https://go.dev/play/p/g2j08F_zZky)
|
||||||
- **<big>Xnor</big>** : 如果 a 和 b 都是真的或 a 和 b 均是假的,则返回 true。
|
- **<big>Xnor</big>** : 如果 a 和 b 都是真的或 a 和 b 均是假的,则返回 true。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Xnor)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Xnor)]
|
||||||
[[play](https://go.dev/play/p/OuDB9g51643)]]
|
[[play](https://go.dev/play/p/OuDB9g51643)]]
|
||||||
- **<big>Nand</big>** : 如果 a 和 b 都为真,返回 false,否则返回 true
|
- **<big>Nand</big>** : 如果 a 和 b 都为真,返回 false,否则返回 true
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nand)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nand)]
|
||||||
[[play](https://go.dev/play/p/vSRMLxLIbq8)]
|
[[play](https://go.dev/play/p/vSRMLxLIbq8)]
|
||||||
@@ -247,7 +247,10 @@ import "github.com/duke-git/lancet/v2/convertor"
|
|||||||
[[play](https://go.dev/play/p/zI6xsmuQRbn)]
|
[[play](https://go.dev/play/p/zI6xsmuQRbn)]
|
||||||
- **<big>DeepClone</big>** : 创建一个传入值的深拷贝, 无法克隆结构体的非导出字段。
|
- **<big>DeepClone</big>** : 创建一个传入值的深拷贝, 无法克隆结构体的非导出字段。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#DeepClone)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#DeepClone)]
|
||||||
|
[[play](https://go.dev/play/p/j4DP5dquxnk)]
|
||||||
|
- **<big>CopyProperties</big>** : 拷贝不同结构体之间的同名字段。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#CopyProperties)]
|
||||||
|
[[play](https://go.dev/play/p/FOVY3XJL-6B)]
|
||||||
|
|
||||||
### 5. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。
|
### 5. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。
|
||||||
|
|
||||||
@@ -257,103 +260,101 @@ import "github.com/duke-git/lancet/v2/cryptor"
|
|||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
|
|
||||||
- **<big>AesEcbEncrypt</big>** : 使用AES ECB算法模式加密数据。
|
- **<big>AesEcbEncrypt</big>** : 使用 AES ECB 算法模式加密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbEncrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbEncrypt)]
|
||||||
[[play](https://go.dev/play/p/zI6xsmuQRbn)]
|
[[play](https://go.dev/play/p/zI6xsmuQRbn)]
|
||||||
- **<big>AesEcbDecrypt</big>** : 使用AES ECB算法模解密数据。
|
- **<big>AesEcbDecrypt</big>** : 使用 AES ECB 算法模解密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbDecrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbDecrypt)]
|
||||||
[[play](https://go.dev/play/p/zI6xsmuQRbn)]
|
[[play](https://go.dev/play/p/zI6xsmuQRbn)]
|
||||||
- **<big>AesCbcEncrypt</big>** : 使用AES CBC算法模式加密数据。
|
- **<big>AesCbcEncrypt</big>** : 使用 AES CBC 算法模式加密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcEncrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcEncrypt)]
|
||||||
[[play](https://go.dev/play/p/IOq_g8_lKZD)]
|
[[play](https://go.dev/play/p/IOq_g8_lKZD)]
|
||||||
- **<big>AesCbcDecrypt</big>** : 使用AES CBC算法模式解密数据。
|
- **<big>AesCbcDecrypt</big>** : 使用 AES CBC 算法模式解密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcDecrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcDecrypt)]
|
||||||
[[play](https://go.dev/play/p/IOq_g8_lKZD)]
|
[[play](https://go.dev/play/p/IOq_g8_lKZD)]
|
||||||
- **<big>AesCtrCrypt</big>** : 使用AES CTR算法模式加密/解密数据。
|
- **<big>AesCtrCrypt</big>** : 使用 AES CTR 算法模式加密/解密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCtrCrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCtrCrypt)]
|
||||||
[[play](https://go.dev/play/p/SpaZO0-5Nsp)]
|
[[play](https://go.dev/play/p/SpaZO0-5Nsp)]
|
||||||
- **<big>AesCfbEncrypt</big>** : 使用AES CFB算法模式加密数据。
|
- **<big>AesCfbEncrypt</big>** : 使用 AES CFB 算法模式加密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbEncrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbEncrypt)]
|
||||||
[[play](https://go.dev/play/p/tfkF10B13kH)]
|
[[play](https://go.dev/play/p/tfkF10B13kH)]
|
||||||
- **<big>AesCfbDecrypt</big>** : 使用AES CFB算法模式解密数据。
|
- **<big>AesCfbDecrypt</big>** : 使用 AES CFB 算法模式解密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbDecrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbDecrypt)]
|
||||||
[[play](https://go.dev/play/p/tfkF10B13kH)]
|
[[play](https://go.dev/play/p/tfkF10B13kH)]
|
||||||
- **<big>AesOfbEncrypt</big>** : 使用AES OFB算法模式加密数据。
|
- **<big>AesOfbEncrypt</big>** : 使用 AES OFB 算法模式加密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbEncrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbEncrypt)]
|
||||||
[[play](https://go.dev/play/p/VtHxtkUj-3F)]
|
[[play](https://go.dev/play/p/VtHxtkUj-3F)]
|
||||||
- **<big>AesOfbDecrypt</big>** : 使用AES OFB算法模式解密数据。
|
- **<big>AesOfbDecrypt</big>** : 使用 AES OFB 算法模式解密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbDecrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbDecrypt)]
|
||||||
[[play](https://go.dev/play/p/VtHxtkUj-3F)]
|
[[play](https://go.dev/play/p/VtHxtkUj-3F)]
|
||||||
- **<big>Base64StdEncode</big>** : 将字符串base64编码。
|
- **<big>Base64StdEncode</big>** : 将字符串 base64 编码。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdEncode)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdEncode)]
|
||||||
[[play](https://go.dev/play/p/VOaUyQUreoK)]
|
[[play](https://go.dev/play/p/VOaUyQUreoK)]
|
||||||
- **<big>Base64StdDecode</big>** : 解码base64字符串。
|
- **<big>Base64StdDecode</big>** : 解码 base64 字符串。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdDecode)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdDecode)]
|
||||||
[[play](https://go.dev/play/p/RWQylnJVgIe)]
|
[[play](https://go.dev/play/p/RWQylnJVgIe)]
|
||||||
- **<big>DesEcbEncrypt</big>** : 使用DES ECB算法模式加密数据。
|
- **<big>DesEcbEncrypt</big>** : 使用 DES ECB 算法模式加密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbEncrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbEncrypt)]
|
||||||
[[play](https://go.dev/play/p/8qivmPeZy4P)]
|
[[play](https://go.dev/play/p/8qivmPeZy4P)]
|
||||||
- **<big>DesEcbDecrypt</big>** : 使用DES ECB算法模解密数据。
|
- **<big>DesEcbDecrypt</big>** : 使用 DES ECB 算法模解密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbDecrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbDecrypt)]
|
||||||
[[play](https://go.dev/play/p/8qivmPeZy4P)]
|
[[play](https://go.dev/play/p/8qivmPeZy4P)]
|
||||||
- **<big>DesCbcEncrypt</big>** : 使用DES CBC算法模式加密数据。
|
- **<big>DesCbcEncrypt</big>** : 使用 DES CBC 算法模式加密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcEncrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcEncrypt)]
|
||||||
[[play](https://go.dev/play/p/4cC4QvWfe3_1)]
|
[[play](https://go.dev/play/p/4cC4QvWfe3_1)]
|
||||||
- **<big>DesCbcDecrypt</big>** : 使用DES CBC算法模式解密数据。
|
- **<big>DesCbcDecrypt</big>** : 使用 DES CBC 算法模式解密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcDecrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcDecrypt)]
|
||||||
[[play](https://go.dev/play/p/4cC4QvWfe3_1)]
|
[[play](https://go.dev/play/p/4cC4QvWfe3_1)]
|
||||||
- **<big>DesCtrCrypt</big>** : 使用DES CTR算法模式加密/解密数据。
|
- **<big>DesCtrCrypt</big>** : 使用 DES CTR 算法模式加密/解密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCtrCrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCtrCrypt)]
|
||||||
[[play](https://go.dev/play/p/9-T6OjKpcdw)]
|
[[play](https://go.dev/play/p/9-T6OjKpcdw)]
|
||||||
- **<big>DesCfbEncrypt</big>** : 使用DES CFB算法模式加密数据。
|
- **<big>DesCfbEncrypt</big>** : 使用 DES CFB 算法模式加密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbEncrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbEncrypt)]
|
||||||
[[play](https://go.dev/play/p/y-eNxcFBlxL)]
|
[[play](https://go.dev/play/p/y-eNxcFBlxL)]
|
||||||
- **<big>DesCfbDecrypt</big>** : 使用DES CFB算法模式解密数据。
|
- **<big>DesCfbDecrypt</big>** : 使用 DES CFB 算法模式解密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbDecrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbDecrypt)]
|
||||||
[[play](https://go.dev/play/p/y-eNxcFBlxL)]
|
[[play](https://go.dev/play/p/y-eNxcFBlxL)]
|
||||||
- **<big>DesOfbEncrypt</big>** : 使用DES OFB算法模式加密数据。
|
- **<big>DesOfbEncrypt</big>** : 使用 DES OFB 算法模式加密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbEncrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbEncrypt)]
|
||||||
[[play](https://go.dev/play/p/74KmNadjN1J)]
|
[[play](https://go.dev/play/p/74KmNadjN1J)]
|
||||||
- **<big>DesOfbDecrypt</big>** : 使用DES OFB算法模式解密数据。
|
- **<big>DesOfbDecrypt</big>** : 使用 DES OFB 算法模式解密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbDecrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbDecrypt)]
|
||||||
[[play](https://go.dev/play/p/74KmNadjN1J)]
|
[[play](https://go.dev/play/p/74KmNadjN1J)]
|
||||||
- **<big>HmacMd5</big>** : 返回字符串md5 hmac值。
|
- **<big>HmacMd5</big>** : 返回字符串 md5 hmac 值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacMd5)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacMd5)]
|
||||||
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
||||||
- **<big>HmacSha1</big>** : 返回字符串sha1 hmac值。
|
- **<big>HmacSha1</big>** : 返回字符串 sha1 hmac 值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha1)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha1)]
|
||||||
[[play](https://go.dev/play/p/1UI4oQ4WXKM)]
|
[[play](https://go.dev/play/p/1UI4oQ4WXKM)]
|
||||||
- **<big>HmacSha256</big>** : 返回字符串sha256 hmac值。
|
- **<big>HmacSha256</big>** : 返回字符串 sha256 hmac 值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha256)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha256)]
|
||||||
[[play](https://go.dev/play/p/HhpwXxFhhC0)]
|
[[play](https://go.dev/play/p/HhpwXxFhhC0)]
|
||||||
- **<big>HmacSha512</big>** : 返回字符串sha256 hmac值。
|
- **<big>HmacSha512</big>** : 返回字符串 sha256 hmac 值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha512)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha512)]
|
||||||
[[play](https://go.dev/play/p/59Od6m4A0Ud)]
|
[[play](https://go.dev/play/p/59Od6m4A0Ud)]
|
||||||
- **<big>Md5String</big>** : 返回字符串md5值。
|
- **<big>Md5String</big>** : 返回字符串 md5 值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5String)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5String)]
|
||||||
[[play](https://go.dev/play/p/1bLcVetbTOI)]
|
[[play](https://go.dev/play/p/1bLcVetbTOI)]
|
||||||
- **<big>Md5File</big>** : 返回文件md5值。
|
- **<big>Md5File</big>** : 返回文件 md5 值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5File)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5File)]
|
||||||
- **<big>Sha1</big>** : 返回字符串sha1哈希值。
|
- **<big>Sha1</big>** : 返回字符串 sha1 哈希值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha1)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha1)]
|
||||||
[[play](https://go.dev/play/p/_m_uoD1deMT)]
|
[[play](https://go.dev/play/p/_m_uoD1deMT)]
|
||||||
- **<big>Sha256</big>** :返回字符串sha256哈希值。
|
- **<big>Sha256</big>** :返回字符串 sha256 哈希值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha256)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha256)]
|
||||||
[[play](https://go.dev/play/p/tU9tfBMIAr1)]
|
[[play](https://go.dev/play/p/tU9tfBMIAr1)]
|
||||||
- **<big>Sha512</big>** : 返回字符串sha512哈希值。
|
- **<big>Sha512</big>** : 返回字符串 sha512 哈希值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha512)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha512)]
|
||||||
[[play](https://go.dev/play/p/3WsvLYZxsHa)]
|
[[play](https://go.dev/play/p/3WsvLYZxsHa)]
|
||||||
- **<big>GenerateRsaKey</big>** : 在当前目录下创建rsa私钥文件和公钥文件。
|
- **<big>GenerateRsaKey</big>** : 在当前目录下创建 rsa 私钥文件和公钥文件。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#GenerateRsaKey)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#GenerateRsaKey)]
|
||||||
[[play](https://go.dev/play/p/zutRHrDqs0X)]
|
[[play](https://go.dev/play/p/zutRHrDqs0X)]
|
||||||
- **<big>RsaEncrypt</big>** : 用公钥文件ras加密数据。
|
- **<big>RsaEncrypt</big>** : 用公钥文件 ras 加密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaEncrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaEncrypt)]
|
||||||
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
||||||
- **<big>RsaDecrypt</big>** : 用私钥文件rsa解密数据。
|
- **<big>RsaDecrypt</big>** : 用私钥文件 rsa 解密数据。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt)]
|
||||||
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 6. datetime 日期时间处理包,格式化日期,比较日期。
|
### 6. datetime 日期时间处理包,格式化日期,比较日期。
|
||||||
|
|
||||||
@@ -429,32 +430,30 @@ import "github.com/duke-git/lancet/v2/datetime"
|
|||||||
- **<big>FormatStrToTime</big>** : 将字符串格式化成时间。
|
- **<big>FormatStrToTime</big>** : 将字符串格式化成时间。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatStrToTime)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatStrToTime)]
|
||||||
[[play](https://go.dev/play/p/1h9FwdU8ql4)]
|
[[play](https://go.dev/play/p/1h9FwdU8ql4)]
|
||||||
- **<big>NewUnix</big>** : 创建一个unix时间戳。
|
- **<big>NewUnix</big>** : 创建一个 unix 时间戳。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnix)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnix)]
|
||||||
[[play](https://go.dev/play/p/psoSuh_kLRt)]
|
[[play](https://go.dev/play/p/psoSuh_kLRt)]
|
||||||
- **<big>NewUnixNow</big>** : 创建一个当前时间的unix时间戳。
|
- **<big>NewUnixNow</big>** : 创建一个当前时间的 unix 时间戳。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnixNow)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnixNow)]
|
||||||
[[play](https://go.dev/play/p/U4PPx-9D0oz)]
|
[[play](https://go.dev/play/p/U4PPx-9D0oz)]
|
||||||
- **<big>NewFormat</big>** : 创建一个yyyy-mm-dd hh:mm:ss格式时间字符串的unix时间戳。
|
- **<big>NewFormat</big>** : 创建一个 yyyy-mm-dd hh:mm:ss 格式时间字符串的 unix 时间戳。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewFormat)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewFormat)]
|
||||||
[[play](https://go.dev/play/p/VkW08ZOaXPZ)]
|
[[play](https://go.dev/play/p/VkW08ZOaXPZ)]
|
||||||
- **<big>NewISO8601</big>** : 创建一个iso8601格式时间字符串的unix时间戳。
|
- **<big>NewISO8601</big>** : 创建一个 iso8601 格式时间字符串的 unix 时间戳。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewISO8601)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewISO8601)]
|
||||||
[[play](https://go.dev/play/p/mkhOHQkdeA2)]
|
[[play](https://go.dev/play/p/mkhOHQkdeA2)]
|
||||||
- **<big>ToUnix</big>** : 返回unix时间戳。
|
- **<big>ToUnix</big>** : 返回 unix 时间戳。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToUnix)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToUnix)]
|
||||||
[[play](https://go.dev/play/p/_LUiwAdocjy)]
|
[[play](https://go.dev/play/p/_LUiwAdocjy)]
|
||||||
- **<big>ToFormat</big>** : 返回格式'yyyy-mm-dd hh:mm:ss'的日期字符串。
|
- **<big>ToFormat</big>** : 返回格式'yyyy-mm-dd hh:mm:ss'的日期字符串。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormat)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormat)]
|
||||||
[[play](https://go.dev/play/p/VkW08ZOaXPZ)]
|
[[play](https://go.dev/play/p/VkW08ZOaXPZ)]
|
||||||
- **<big>ToFormatForTpl</big>** : 返回tpl格式指定的日期字符串。
|
- **<big>ToFormatForTpl</big>** : 返回 tpl 格式指定的日期字符串。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormatForTpl)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormatForTpl)]
|
||||||
[[play](https://go.dev/play/p/nyXxXcQJ8L5)]
|
[[play](https://go.dev/play/p/nyXxXcQJ8L5)]
|
||||||
- **<big>ToIso8601</big>** : 返回iso8601日期字符串。
|
- **<big>ToIso8601</big>** : 返回 iso8601 日期字符串。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)]
|
||||||
[[play](https://go.dev/play/p/mkhOHQkdeA2)]
|
[[play](https://go.dev/play/p/mkhOHQkdeA2)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 7. datastructure 包含一些普通的数据结构实现。例如:list, linklist, stack, queue, set, tree, graph.
|
### 7. datastructure 包含一些普通的数据结构实现。例如:list, linklist, stack, queue, set, tree, graph.
|
||||||
|
|
||||||
@@ -483,14 +482,11 @@ import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
|||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/set_zh-CN.md)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/set_zh-CN.md)]
|
||||||
- **<big>Tree</big>** : 二叉搜索树。
|
- **<big>Tree</big>** : 二叉搜索树。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/tree_zh-CN.md)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/tree_zh-CN.md)]
|
||||||
- **<big>Heap</big>** : 二叉max堆。
|
- **<big>Heap</big>** : 二叉 max 堆。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/heap_zh-CN.md)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/heap_zh-CN.md)]
|
||||||
- **<big>Hashmap</big>** : 哈希映射。
|
- **<big>Hashmap</big>** : 哈希映射。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap_zh-CN.md)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap_zh-CN.md)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 8. fileutil 包含文件基本操作。
|
### 8. fileutil 包含文件基本操作。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -565,35 +561,34 @@ import "github.com/duke-git/lancet/v2/function"
|
|||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
|
|
||||||
- **<big>After</big>** : 创建一个函数,当该函数被调用n或更多次之后将执行传入的函数。
|
- **<big>After</big>** : 创建一个函数,当该函数被调用 n 或更多次之后将执行传入的函数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#After)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#After)]
|
||||||
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
|
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
|
||||||
- **<big>Before</big>** : 创建一个函数,当该函数被调用不超过n次时,将执行执行传入的函数。
|
- **<big>Before</big>** : 创建一个函数,当该函数被调用不超过 n 次时,将执行执行传入的函数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Before)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Before)]
|
||||||
[[play](https://go.dev/play/p/0HqUDIFZ3IL)]
|
[[play](https://go.dev/play/p/0HqUDIFZ3IL)]
|
||||||
- **<big>CurryFn</big>** : 创建柯里化函数。
|
- **<big>CurryFn</big>** : 创建柯里化函数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#CurryFn)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#CurryFn)]
|
||||||
[[play](https://go.dev/play/p/5HopfDwANKX)]
|
[[play](https://go.dev/play/p/5HopfDwANKX)]
|
||||||
- **<big>Compose</big>** : 从右至左组合函数列表fnList,返回组合后的函数。
|
- **<big>Compose</big>** : 从右至左组合函数列表 fnList,返回组合后的函数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Compose)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Compose)]
|
||||||
[[play](https://go.dev/play/p/KKfugD4PKYF)]
|
[[play](https://go.dev/play/p/KKfugD4PKYF)]
|
||||||
- **<big>Delay</big>** : 延迟delay时间后调用函数。
|
- **<big>Delay</big>** : 延迟 delay 时间后调用函数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Delay)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Delay)]
|
||||||
[[play](https://go.dev/play/p/Ivtc2ZE-Tye)]
|
[[play](https://go.dev/play/p/Ivtc2ZE-Tye)]
|
||||||
- **<big>Debounced</big>** : 创建一个debounced函数,该函数延迟调用fn直到自上次调用debounced函数后等待持续时间过去。
|
- **<big>Debounced</big>** : 创建一个 debounced 函数,该函数延迟调用 fn 直到自上次调用 debounced 函数后等待持续时间过去。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Debounced)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Debounced)]
|
||||||
[[play](https://go.dev/play/p/absuEGB_GN7)]
|
[[play](https://go.dev/play/p/absuEGB_GN7)]
|
||||||
- **<big>Schedule</big>** : 每次持续时间调用函数,直到关闭返回的channel。
|
- **<big>Schedule</big>** : 每次持续时间调用函数,直到关闭返回的 channel。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Schedule)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Schedule)]
|
||||||
[[play](https://go.dev/play/p/hbON-Xeyn5N)]
|
[[play](https://go.dev/play/p/hbON-Xeyn5N)]
|
||||||
- **<big>Pipeline</big>** : 从右至左执行函数列表。
|
- **<big>Pipeline</big>** : 从右至左执行函数列表。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Pipeline)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Pipeline)]
|
||||||
[[play](https://go.dev/play/p/mPdUVvj6HD6)]
|
[[play](https://go.dev/play/p/mPdUVvj6HD6)]
|
||||||
- **<big>Watcher</big>** : Watcher用于记录代码执行时间。可以启动/停止/重置手表定时器。获取函数执行的时间。
|
- **<big>Watcher</big>** : Watcher 用于记录代码执行时间。可以启动/停止/重置手表定时器。获取函数执行的时间。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)]
|
||||||
[[play](https://go.dev/play/p/l2yrOpCLd1I)]
|
[[play](https://go.dev/play/p/l2yrOpCLd1I)]
|
||||||
|
|
||||||
|
|
||||||
### 11. maputil 包括一些操作 map 的函数.
|
### 11. maputil 包括一些操作 map 的函数.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -608,12 +603,30 @@ import "github.com/duke-git/lancet/v2/maputil"
|
|||||||
- **<big>Filter</big>** : 迭代 map 中的每对 key 和 value,返回 map,其中的 key 和 value 符合 predicate 函数。
|
- **<big>Filter</big>** : 迭代 map 中的每对 key 和 value,返回 map,其中的 key 和 value 符合 predicate 函数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Filter)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Filter)]
|
||||||
[[play](https://go.dev/play/p/fSvF3wxuNG7)]
|
[[play](https://go.dev/play/p/fSvF3wxuNG7)]
|
||||||
|
- **<big>FilterByKeys</big>** : 迭代 map, 返回一个新 map,其 key 都是给定的 key 值。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#FilterByKeys)]
|
||||||
|
[[play](https://go.dev/play/p/7ov6BJHbVqh)]
|
||||||
|
- **<big>FilterByValues</big>** : 迭代 map, 返回一个新 map,其 value 都是给定的 value 值。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#FilterByValues)]
|
||||||
|
[[play](https://go.dev/play/p/P3-9MdcXegR)]
|
||||||
|
- **<big>OmitBy</big>** : Filter 的反向操作, 迭代 map 中的每对 key 和 value, 删除符合 predicate 函数的 key, value, 返回新 map。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#OmitBy)]
|
||||||
|
[[play](https://go.dev/play/p/YJM4Hj5hNwm)]
|
||||||
|
- **<big>OmitByKeys</big>** : FilterByKeys 的反向操作, 迭代 map, 返回一个新 map,其 key 不包括给定的 key 值。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#OmitByKeys)]
|
||||||
|
[[play](https://go.dev/play/p/jXGrWDBfSRp)]
|
||||||
|
- **<big>OmitByValues</big>** : FilterByValues 的反向操作, 迭代 map, 返回一个新 map,其 value 不包括给定的 value 值。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#OmitByValues)]
|
||||||
|
[[play](https://go.dev/play/p/XB7Y10uw20_U)]
|
||||||
- **<big>Intersect</big>** : 多个 map 的交集操作。
|
- **<big>Intersect</big>** : 多个 map 的交集操作。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Intersect)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Intersect)]
|
||||||
[[play](https://go.dev/play/p/Zld0oj3sjcC)]
|
[[play](https://go.dev/play/p/Zld0oj3sjcC)]
|
||||||
- **<big>Keys</big>** : 返回 map 中所有 key 组成的切片。
|
- **<big>Keys</big>** : 返回 map 中所有 key 组成的切片。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Keys)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Keys)]
|
||||||
[[play](https://go.dev/play/p/xNB5bTb97Wd)]
|
[[play](https://go.dev/play/p/xNB5bTb97Wd)]
|
||||||
|
- **<big>KeysBy</big>** : 创建一个切片,其元素是每个 map 的 key 调用 mapper 函数的结果。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#KeysBy)]
|
||||||
|
[[play](https://go.dev/play/p/hI371iB8Up8)]
|
||||||
- **<big>Merge</big>** : 合并多个 map, 相同的 key 会被之后的 key 覆盖。
|
- **<big>Merge</big>** : 合并多个 map, 相同的 key 会被之后的 key 覆盖。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Merge)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Merge)]
|
||||||
[[play](https://go.dev/play/p/H95LENF1uB-)]
|
[[play](https://go.dev/play/p/H95LENF1uB-)]
|
||||||
@@ -623,6 +636,24 @@ import "github.com/duke-git/lancet/v2/maputil"
|
|||||||
- **<big>Values</big>** : 返回 map 中所有 values 组成的切片
|
- **<big>Values</big>** : 返回 map 中所有 values 组成的切片
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Values)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Values)]
|
||||||
[[play](https://go.dev/play/p/CBKdUc5FTW6)]
|
[[play](https://go.dev/play/p/CBKdUc5FTW6)]
|
||||||
|
- **<big>ValuesBy</big>** : 创建一个切片,其元素是每个 map 的 value 调用 mapper 函数的结果。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#ValuesBy)]
|
||||||
|
[[play](https://go.dev/play/p/sg9-oRidh8f)]
|
||||||
|
- **<big>MapKeys</big>** : 操作 map 的每个 key,然后转为新的 map。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#MapKeys)]
|
||||||
|
[[play](https://go.dev/play/p/8scDxWeBDKd)]
|
||||||
|
- **<big>MapValues</big>** : 操作 map 的每个 value,然后转为新的 map。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#MapValues)]
|
||||||
|
[[play](https://go.dev/play/p/g92aY3fc7Iw)]
|
||||||
|
- **<big>Entries</big>** : 将 map 转换为键/值对切片。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#Entries)]
|
||||||
|
[[play](https://go.dev/play/p/Ltb11LNcElY)]
|
||||||
|
- **<big>FromEntries</big>** : 基于键/值对的切片创建 map。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#FromEntries)]
|
||||||
|
[[play](https://go.dev/play/p/fTdu4sCNjQO)]
|
||||||
|
- **<big>Transform</big>** : 将 map 转换为其他类型的 map。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#Transform)]
|
||||||
|
[[play](https://go.dev/play/p/P6ovfToM3zj)]
|
||||||
- **<big>IsDisjoint</big>** : 验证两个 map 是否具有不同的 key。
|
- **<big>IsDisjoint</big>** : 验证两个 map 是否具有不同的 key。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#IsDisjoint)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#IsDisjoint)]
|
||||||
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
|
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
|
||||||
@@ -680,64 +711,61 @@ import "github.com/duke-git/lancet/v2/netutil"
|
|||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
|
|
||||||
- **<big>ConvertMapToQueryString</big>** : 将map转换成http查询字符串。
|
- **<big>ConvertMapToQueryString</big>** : 将 map 转换成 http 查询字符串。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ConvertMapToQueryString)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ConvertMapToQueryString)]
|
||||||
[[play](https://go.dev/play/p/jnNt_qoSnRi)]
|
[[play](https://go.dev/play/p/jnNt_qoSnRi)]
|
||||||
- **<big>EncodeUrl</big>** : 编码url query string的值(?a=1&b=[2] -> ?a=1&b=%5B2%5D)。
|
- **<big>EncodeUrl</big>** : 编码 url query string 的值(?a=1&b=[2] -> ?a=1&b=%5B2%5D)。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#EncodeUrl)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#EncodeUrl)]
|
||||||
[[play](https://go.dev/play/p/bsZ6BRC4uKI)]
|
[[play](https://go.dev/play/p/bsZ6BRC4uKI)]
|
||||||
- **<big>GetInternalIp</big>** : 获取内部ipv4。
|
- **<big>GetInternalIp</big>** : 获取内部 ipv4。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetInternalIp)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetInternalIp)]
|
||||||
[[play](https://go.dev/play/p/5mbu-gFp7ei)]
|
[[play](https://go.dev/play/p/5mbu-gFp7ei)]
|
||||||
- **<big>GetIps</big>** : 获取系统ipv4地址列表。
|
- **<big>GetIps</big>** : 获取系统 ipv4 地址列表。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetIps)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetIps)]
|
||||||
[[play](https://go.dev/play/p/NUFfcEmukx1)]
|
[[play](https://go.dev/play/p/NUFfcEmukx1)]
|
||||||
- **<big>GetMacAddrs</big>** : 获取系统mac地址列。
|
- **<big>GetMacAddrs</big>** : 获取系统 mac 地址列。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetMacAddrs)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetMacAddrs)]
|
||||||
[[play](https://go.dev/play/p/Rq9UUBS_Xp1)]
|
[[play](https://go.dev/play/p/Rq9UUBS_Xp1)]
|
||||||
- **<big>GetPublicIpInfo</big>** : 获取[公网ip信息](http://ip-api.com/json/).
|
- **<big>GetPublicIpInfo</big>** : 获取[公网 ip 信息](http://ip-api.com/json/).
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetPublicIpInfo)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetPublicIpInfo)]
|
||||||
[[play](https://go.dev/play/p/YDxIfozsRHR)]
|
[[play](https://go.dev/play/p/YDxIfozsRHR)]
|
||||||
- **<big>GetRequestPublicIp</big>** : 获取http请求ip。
|
- **<big>GetRequestPublicIp</big>** : 获取 http 请求 ip。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetRequestPublicIp)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetRequestPublicIp)]
|
||||||
[[play](https://go.dev/play/p/kxU-YDc_eBo)]
|
[[play](https://go.dev/play/p/kxU-YDc_eBo)]
|
||||||
- **<big>IsPublicIP</big>** : 判断ip是否是公共ip。
|
- **<big>IsPublicIP</big>** : 判断 ip 是否是公共 ip。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsPublicIP)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsPublicIP)]
|
||||||
[[play](https://go.dev/play/p/nmktSQpJZnn)]
|
[[play](https://go.dev/play/p/nmktSQpJZnn)]
|
||||||
- **<big>IsInternalIP</big>** : 判断ip是否是局域网ip。
|
- **<big>IsInternalIP</big>** : 判断 ip 是否是局域网 ip。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsInternalIP)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsInternalIP)]
|
||||||
[[play](https://go.dev/play/p/sYGhXbgO4Cb)]
|
[[play](https://go.dev/play/p/sYGhXbgO4Cb)]
|
||||||
- **<big>HttpRequest</big>** : 用于抽象HTTP请求实体的结构。
|
- **<big>HttpRequest</big>** : 用于抽象 HTTP 请求实体的结构。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpRequest)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpRequest)]
|
||||||
[[play](https://go.dev/play/p/jUSgynekH7G)]
|
[[play](https://go.dev/play/p/jUSgynekH7G)]
|
||||||
- **<big>HttpClient</big>** : 用于发送HTTP请求。
|
- **<big>HttpClient</big>** : 用于发送 HTTP 请求。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpClient)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpClient)]
|
||||||
[[play](https://go.dev/play/p/jUSgynekH7G)]
|
[[play](https://go.dev/play/p/jUSgynekH7G)]
|
||||||
- **<big>SendRequest</big>** : 发送http请求。
|
- **<big>SendRequest</big>** : 发送 http 请求。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#SendRequest)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#SendRequest)]
|
||||||
[[play](https://go.dev/play/p/jUSgynekH7G)]
|
[[play](https://go.dev/play/p/jUSgynekH7G)]
|
||||||
- **<big>DecodeResponse</big>** : 解析http响应体到目标结构体。
|
- **<big>DecodeResponse</big>** : 解析 http 响应体到目标结构体。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#DecodeResponse)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#DecodeResponse)]
|
||||||
[[play](https://go.dev/play/p/jUSgynekH7G)]
|
[[play](https://go.dev/play/p/jUSgynekH7G)]
|
||||||
- **<big>StructToUrlValues</big>** : 将结构体转为url values, 仅转化结构体导出字段并且包含`json` tag。
|
- **<big>StructToUrlValues</big>** : 将结构体转为 url values, 仅转化结构体导出字段并且包含`json` tag。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#StructToUrlValues)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#StructToUrlValues)]
|
||||||
[[play](https://go.dev/play/p/pFqMkM40w9z)]
|
[[play](https://go.dev/play/p/pFqMkM40w9z)]
|
||||||
- **<big>HttpGet<sup>deprecated</sup></big>** : 发送http get请求(已弃用:SendRequest代替)。
|
- **<big>HttpGet<sup>deprecated</sup></big>** : 发送 http get 请求(已弃用:SendRequest 代替)。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpGet)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpGet)]
|
||||||
- **<big>HttpDelete<sup>deprecated</sup></big>** : 发送http delete请求(已弃用:SendRequest代替)。
|
- **<big>HttpDelete<sup>deprecated</sup></big>** : 发送 http delete 请求(已弃用:SendRequest 代替)。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpDelete)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpDelete)]
|
||||||
- **<big>HttpPost<sup>deprecated</sup></big>** : 发送http post请求(已弃用:SendRequest代替)。
|
- **<big>HttpPost<sup>deprecated</sup></big>** : 发送 http post 请求(已弃用:SendRequest 代替)。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPost)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPost)]
|
||||||
- **<big>HttpPut<sup>deprecated</sup></big>** : 发送http put请求(已弃用:SendRequest代替)。
|
- **<big>HttpPut<sup>deprecated</sup></big>** : 发送 http put 请求(已弃用:SendRequest 代替)。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPut)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPut)]
|
||||||
- **<big>HttpPatch<sup>deprecated</sup></big>** : 发送http patch请求(已弃用:SendRequest代替)。
|
- **<big>HttpPatch<sup>deprecated</sup></big>** : 发送 http patch 请求(已弃用:SendRequest 代替)。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch)]
|
||||||
- **<big>ParseHttpResponse</big>** : 解析http响应体到目标结构体。
|
- **<big>ParseHttpResponse</big>** : 解析 http 响应体到目标结构体。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 14. random 随机数生成器包,可以生成随机[]bytes, int, string。
|
### 14. random 随机数生成器包,可以生成随机[]bytes, int, string。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -749,7 +777,7 @@ import "github.com/duke-git/lancet/v2/random"
|
|||||||
- **<big>RandBytes</big>** : 生成随机字节切片。
|
- **<big>RandBytes</big>** : 生成随机字节切片。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandBytes)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandBytes)]
|
||||||
[[play](https://go.dev/play/p/EkiLESeXf8d)]
|
[[play](https://go.dev/play/p/EkiLESeXf8d)]
|
||||||
- **<big>RandInt</big>** : 生成随机int, 范围[min, max)。
|
- **<big>RandInt</big>** : 生成随机 int, 范围[min, max)。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandInt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandInt)]
|
||||||
[[play](https://go.dev/play/p/pXyyAAI5YxD)]
|
[[play](https://go.dev/play/p/pXyyAAI5YxD)]
|
||||||
- **<big>RandString</big>** : 生成给定长度的随机字符串,只包含字母(a-zA-Z)。
|
- **<big>RandString</big>** : 生成给定长度的随机字符串,只包含字母(a-zA-Z)。
|
||||||
@@ -767,11 +795,9 @@ import "github.com/duke-git/lancet/v2/random"
|
|||||||
- **<big>RandNumeralOrLetter</big>** : 生成给定长度的随机字符串(数字+字母)。
|
- **<big>RandNumeralOrLetter</big>** : 生成给定长度的随机字符串(数字+字母)。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandNumeralOrLetter)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandNumeralOrLetter)]
|
||||||
[[play](https://go.dev/play/p/19CEQvpx2jD)]
|
[[play](https://go.dev/play/p/19CEQvpx2jD)]
|
||||||
- **<big>UUIdV4</big>** : 生成UUID v4字符串。
|
- **<big>UUIdV4</big>** : 生成 UUID v4 字符串。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#UUIdV4)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#UUIdV4)]
|
||||||
[[play](https://go.dev/play/p/_Z9SFmr28ft)]
|
[[play](https://go.dev/play/p/_Z9SFmr28ft)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 15. retry 重试执行函数直到函数运行成功或被 context cancel。
|
### 15. retry 重试执行函数直到函数运行成功或被 context cancel。
|
||||||
|
|
||||||
@@ -781,24 +807,22 @@ import "github.com/duke-git/lancet/v2/retry"
|
|||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
|
|
||||||
- **<big>Context</big>** : 设置重试context参数。
|
- **<big>Context</big>** : 设置重试 context 参数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Context)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Context)]
|
||||||
[[play](https://go.dev/play/p/xnAOOXv9GkS)]
|
[[play](https://go.dev/play/p/xnAOOXv9GkS)]
|
||||||
- **<big>Retry</big>** : 重试执行函数retryFunc,直到函数运行成功,或被context取消。
|
- **<big>Retry</big>** : 重试执行函数 retryFunc,直到函数运行成功,或被 context 取消。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Retry)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Retry)]
|
||||||
[[play](https://go.dev/play/p/nk2XRmagfVF)]
|
[[play](https://go.dev/play/p/nk2XRmagfVF)]
|
||||||
- **<big>RetryFunc</big>** : 重试执行的函数。
|
- **<big>RetryFunc</big>** : 重试执行的函数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryFunc)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryFunc)]
|
||||||
[[play](https://go.dev/play/p/nk2XRmagfVF)]
|
[[play](https://go.dev/play/p/nk2XRmagfVF)]
|
||||||
- **<big>RetryDuration</big>** : 设置重试间隔时间,默认3秒。
|
- **<big>RetryDuration</big>** : 设置重试间隔时间,默认 3 秒。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryDuration)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryDuration)]
|
||||||
[[play](https://go.dev/play/p/nk2XRmagfVF)]
|
[[play](https://go.dev/play/p/nk2XRmagfVF)]
|
||||||
- **<big>RetryTimes</big>** : 设置重试次数,默认5。
|
- **<big>RetryTimes</big>** : 设置重试次数,默认 5。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes)]
|
||||||
[[play](https://go.dev/play/p/ssfVeU2SwLO)]
|
[[play](https://go.dev/play/p/ssfVeU2SwLO)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 16. slice 包含操作切片的方法集合。
|
### 16. slice 包含操作切片的方法集合。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -806,34 +830,38 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
|
|
||||||
- **<big>AppendIfAbsent</big>** : 当前切片中不包含值时,将该值追加到切片中。
|
- **<big>AppendIfAbsent</big>** : 当前切片中不包含值时,将该值追加到切片中。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#AppendIfAbsent)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#AppendIfAbsent)]
|
||||||
[[play](https://go.dev/play/p/GNdv7Jg2Taj)]
|
[[play](https://go.dev/play/p/GNdv7Jg2Taj)]
|
||||||
- **<big>Contain</big>** : 判断slice是否包含value。
|
- **<big>Contain</big>** : 判断 slice 是否包含 value。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Contain)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Contain)]
|
||||||
[[play](https://go.dev/play/p/_454yEHcNjf)]
|
[[play](https://go.dev/play/p/_454yEHcNjf)]
|
||||||
- **<big>ContainSubSlice</big>** : 判断slice是否包含subslice。
|
- **<big>ContainBy</big>** : 根据 predicate 函数判断切片是否包含某个值。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ContainBy)]
|
||||||
|
[[play](https://go.dev/play/p/49tkHfX4GNc)]
|
||||||
|
- **<big>ContainSubSlice</big>** : 判断 slice 是否包含 subslice。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ContainSubSlice)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ContainSubSlice)]
|
||||||
[[play](https://go.dev/play/p/bcuQ3UT6Sev)]
|
[[play](https://go.dev/play/p/bcuQ3UT6Sev)]
|
||||||
- **<big>Chunk</big>** : 按照size参数均分slice。
|
- **<big>Chunk</big>** : 按照 size 参数均分 slice。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Chunk)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Chunk)]
|
||||||
[[play](https://go.dev/play/p/b4Pou5j2L_C)]
|
[[play](https://go.dev/play/p/b4Pou5j2L_C)]
|
||||||
- **<big>Compact</big>** : 去除slice中的假值(false values are false, nil, 0, "")。
|
- **<big>Compact</big>** : 去除 slice 中的假值(false values are false, nil, 0, "")。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Compact)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Compact)]
|
||||||
[[play](https://go.dev/play/p/pO5AnxEr3TK)]
|
[[play](https://go.dev/play/p/pO5AnxEr3TK)]
|
||||||
- **<big>Concat</big>** : 合并多个slices到一个slice中。
|
- **<big>Concat</big>** : 合并多个 slices 到一个 slice 中。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Concat)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Concat)]
|
||||||
[[play](https://go.dev/play/p/gPt-q7zr5mk)]
|
[[play](https://go.dev/play/p/gPt-q7zr5mk)]
|
||||||
- **<big>Count</big>** : 返回切片中指定元素的个数。
|
- **<big>Count</big>** : 返回切片中指定元素的个数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Count)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Count)]
|
||||||
[[play](https://go.dev/play/p/Mj4oiEnQvRJ)]
|
[[play](https://go.dev/play/p/Mj4oiEnQvRJ)]
|
||||||
- **<big>CountBy</big>** : 遍历切片,对每个元素执行函数predicate. 返回符合函数返回值为true的元素的个数。
|
- **<big>CountBy</big>** : 遍历切片,对每个元素执行函数 predicate. 返回符合函数返回值为 true 的元素的个数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#CountBy)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#CountBy)]
|
||||||
[[play](https://go.dev/play/p/tHOccTMDZCC)]
|
[[play](https://go.dev/play/p/tHOccTMDZCC)]
|
||||||
- **<big>Difference</big>** : 创建一个切片,其元素不包含在另一个给定切片中。
|
- **<big>Difference</big>** : 创建一个切片,其元素不包含在另一个给定切片中。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Difference)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Difference)]
|
||||||
[[play](https://go.dev/play/p/VXvadzLzhDa)]
|
[[play](https://go.dev/play/p/VXvadzLzhDa)]
|
||||||
- **<big>DifferenceBy</big>** : 将两个slice中的每个元素调用iteratee函数,并比较它们的返回值,如果不相等返回在slice中对应的值。
|
- **<big>DifferenceBy</big>** : 将两个 slice 中的每个元素调用 iteratee 函数,并比较它们的返回值,如果不相等返回在 slice 中对应的值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DifferenceBy)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DifferenceBy)]
|
||||||
[[play](https://go.dev/play/p/DiivgwM5OnC)]
|
[[play](https://go.dev/play/p/DiivgwM5OnC)]
|
||||||
- **<big>DifferenceWith</big>** : 接受比较器函数,该比较器被调用以将切片的元素与值进行比较。 结果值的顺序和引用由第一个切片确定。
|
- **<big>DifferenceWith</big>** : 接受比较器函数,该比较器被调用以将切片的元素与值进行比较。 结果值的顺序和引用由第一个切片确定。
|
||||||
@@ -842,31 +870,37 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
- **<big>DeleteAt</big>** : 删除切片中指定开始索引到结束索引的元素。
|
- **<big>DeleteAt</big>** : 删除切片中指定开始索引到结束索引的元素。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteAt)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteAt)]
|
||||||
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
|
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
|
||||||
- **<big>Drop</big>** : 从切片头部删除n个元素。
|
- **<big>Drop</big>** : 从切片头部删除 n 个元素。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Drop)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Drop)]
|
||||||
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
|
[[play](https://go.dev/play/p/jnPO2yQsT8H)]
|
||||||
- **<big>DropRight</big>** : 从切片尾部删除n个元素。
|
- **<big>DropRight</big>** : 从切片尾部删除 n 个元素。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DropRight)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DropRight)]
|
||||||
- **<big>DropWhile</big>** : 从切片的头部删除n个元素,这个n个元素满足predicate函数返回true。
|
[[play](https://go.dev/play/p/8bcXvywZezG)]
|
||||||
|
- **<big>DropWhile</big>** : 从切片的头部删除 n 个元素,这个 n 个元素满足 predicate 函数返回 true。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DropWhile)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DropWhile)]
|
||||||
- **<big>DropRightWhile</big>** : 从切片的尾部删除n个元素,这个n个元素满足predicate函数返回true。
|
[[play](https://go.dev/play/p/4rt252UV_qs)]
|
||||||
|
- **<big>DropRightWhile</big>** : 从切片的尾部删除 n 个元素,这个 n 个元素满足 predicate 函数返回 true。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DropRightWhile)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DropRightWhile)]
|
||||||
|
[[play](https://go.dev/play/p/6wyK3zMY56e)]
|
||||||
- **<big>Equal</big>** : 检查两个切片是否相等,相等条件:切片长度相同,元素顺序和值都相同。
|
- **<big>Equal</big>** : 检查两个切片是否相等,相等条件:切片长度相同,元素顺序和值都相同。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Equal)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Equal)]
|
||||||
[[play](https://go.dev/play/p/WcRQJ37ifPa)]
|
[[play](https://go.dev/play/p/WcRQJ37ifPa)]
|
||||||
- **<big>EqualWith</big>** : 检查两个切片是否相等,相等条件:对两个切片的元素调用比较函数comparator,返回true。
|
- **<big>EqualWith</big>** : 检查两个切片是否相等,相等条件:对两个切片的元素调用比较函数 comparator,返回 true。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#EqualWith)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#EqualWith)]
|
||||||
[[play](https://go.dev/play/p/b9iygtgsHI1)]
|
[[play](https://go.dev/play/p/b9iygtgsHI1)]
|
||||||
- **<big>Every</big>** : 如果切片中的所有值都通过谓词函数,则返回true。
|
- **<big>Every</big>** : 如果切片中的所有值都通过谓词函数,则返回 true。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Every)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Every)]
|
||||||
[[play](https://go.dev/play/p/R8U6Sl-j8cD)]
|
[[play](https://go.dev/play/p/R8U6Sl-j8cD)]
|
||||||
- **<big>Filter</big>** : 返回切片中通过predicate函数真值测试的所有元素。
|
- **<big>Filter</big>** : 返回切片中通过 predicate 函数真值测试的所有元素。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Filter)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Filter)]
|
||||||
[[play](https://go.dev/play/p/SdPna-7qK4T)]
|
[[play](https://go.dev/play/p/SdPna-7qK4T)]
|
||||||
- **<big>Find</big>** : 遍历切片的元素,返回第一个通过predicate函数真值测试的元素。
|
- **<big>FilterMap</big>** : 返回一个将 filter 和 map 操作应用于给定切片的切片。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FilterMap)]
|
||||||
|
[[play](https://go.dev/play/p/J94SZ_9MiIe)]
|
||||||
|
- **<big>Find</big>** : 遍历切片的元素,返回第一个通过 predicate 函数真值测试的元素。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Find)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Find)]
|
||||||
[[play](https://go.dev/play/p/CBKeBoHVLgq)]
|
[[play](https://go.dev/play/p/CBKeBoHVLgq)]
|
||||||
- **<big>FindLast</big>** : 从头到尾遍历slice的元素,返回最后一个通过predicate函数真值测试的元素。
|
- **<big>FindLast</big>** : 从头到尾遍历 slice 的元素,返回最后一个通过 predicate 函数真值测试的元素。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindLast)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindLast)]
|
||||||
[[play](https://go.dev/play/p/FFDPV_j7URd)]
|
[[play](https://go.dev/play/p/FFDPV_j7URd)]
|
||||||
- **<big>Flatten</big>** : 将多维切片展平一层。
|
- **<big>Flatten</big>** : 将多维切片展平一层。
|
||||||
@@ -875,19 +909,22 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
- **<big>FlattenDeep</big>** : 将多维切片递归展平到一层。
|
- **<big>FlattenDeep</big>** : 将多维切片递归展平到一层。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FlattenDeep)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FlattenDeep)]
|
||||||
[[play](https://go.dev/play/p/yjYNHPyCFaF)]
|
[[play](https://go.dev/play/p/yjYNHPyCFaF)]
|
||||||
- **<big>ForEach</big>** : 遍历切片的元素并为每个元素调用iteratee函数。
|
- **<big>FlatMap</big>** : 将切片转换为其它类型切片。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FlatMap)]
|
||||||
|
[[play](https://go.dev/play/p/_QARWlWs1N_F)]
|
||||||
|
- **<big>ForEach</big>** : 遍历切片的元素并为每个元素调用 iteratee 函数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ForEach)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ForEach)]
|
||||||
[[play](https://go.dev/play/p/DrPaa4YsHRF)]
|
[[play](https://go.dev/play/p/DrPaa4YsHRF)]
|
||||||
- **<big>GroupBy</big>** : 迭代切片的元素,每个元素将按条件分组,返回两个切片。
|
- **<big>GroupBy</big>** : 迭代切片的元素,每个元素将按条件分组,返回两个切片。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupBy)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupBy)]
|
||||||
[[play](https://go.dev/play/p/QVkPxzPR0iA)]
|
[[play](https://go.dev/play/p/QVkPxzPR0iA)]
|
||||||
- **<big>GroupWith</big>** : 创建一个map,key是iteratee遍历slice中的每个元素返回的结果。值是切片元素。
|
- **<big>GroupWith</big>** : 创建一个 map,key 是 iteratee 遍历 slice 中的每个元素返回的结果。值是切片元素。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupWith)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupWith)]
|
||||||
[[play](https://go.dev/play/p/ApCvMNTLO8a)]
|
[[play](https://go.dev/play/p/ApCvMNTLO8a)]
|
||||||
- **<big>IntSlice<sup>deprecated</sup></big>** : 将接口切片转换为int切片。
|
- **<big>IntSlice<sup>deprecated</sup></big>** : 将接口切片转换为 int 切片。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IntSlice)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IntSlice)]
|
||||||
[[play](https://go.dev/play/p/FdQXF0Vvqs-)]
|
[[play](https://go.dev/play/p/FdQXF0Vvqs-)]
|
||||||
- **<big>InterfaceSlice<sup>deprecated</sup></big>** : 将值转换为interface切片。
|
- **<big>InterfaceSlice<sup>deprecated</sup></big>** : 将值转换为 interface 切片。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InterfaceSlice)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InterfaceSlice)]
|
||||||
[[play](https://go.dev/play/p/FdQXF0Vvqs-)]
|
[[play](https://go.dev/play/p/FdQXF0Vvqs-)]
|
||||||
- **<big>Intersection</big>** : 返回多个切片的交集。
|
- **<big>Intersection</big>** : 返回多个切片的交集。
|
||||||
@@ -902,7 +939,7 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
- **<big>LastIndexOf</big>** : 返回在切片中找到最后一个值的索引,如果找不到该值,则返回-1。
|
- **<big>LastIndexOf</big>** : 返回在切片中找到最后一个值的索引,如果找不到该值,则返回-1。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#LastIndexOf)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#LastIndexOf)]
|
||||||
[[play](https://go.dev/play/p/DokM4cf1IKH)]
|
[[play](https://go.dev/play/p/DokM4cf1IKH)]
|
||||||
- **<big>Map</big>** : 对slice中的每个元素执行map函数以创建一个新切片。
|
- **<big>Map</big>** : 对 slice 中的每个元素执行 map 函数以创建一个新切片。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Map)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Map)]
|
||||||
[[play](https://go.dev/play/p/biaTefqPquw)]
|
[[play](https://go.dev/play/p/biaTefqPquw)]
|
||||||
- **<big>Merge</big>** : 合并多个切片(不会消除重复元素)。
|
- **<big>Merge</big>** : 合并多个切片(不会消除重复元素)。
|
||||||
@@ -911,16 +948,16 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
- **<big>Reverse</big>** : 反转切片中的元素顺序。
|
- **<big>Reverse</big>** : 反转切片中的元素顺序。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reverse)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reverse)]
|
||||||
[[play](https://go.dev/play/p/8uI8f1lwNrQ)]
|
[[play](https://go.dev/play/p/8uI8f1lwNrQ)]
|
||||||
- **<big>Reduce</big>** : 将切片中的元素依次运行iteratee函数,返回运行结果。
|
- **<big>Reduce</big>** : 将切片中的元素依次运行 iteratee 函数,返回运行结果。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reduce)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reduce)]
|
||||||
[[play](https://go.dev/play/p/_RfXJJWIsIm)]
|
[[play](https://go.dev/play/p/_RfXJJWIsIm)]
|
||||||
- **<big>Replace</big>** : 返回切片的副本,其中前n个不重叠的old替换为new。
|
- **<big>Replace</big>** : 返回切片的副本,其中前 n 个不重叠的 old 替换为 new。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Replace)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Replace)]
|
||||||
[[play](https://go.dev/play/p/P5mZp7IhOFo)]
|
[[play](https://go.dev/play/p/P5mZp7IhOFo)]
|
||||||
- **<big>ReplaceAll</big>** : 返回切片的副本,将其中old全部替换为new。
|
- **<big>ReplaceAll</big>** : 返回切片的副本,将其中 old 全部替换为 new。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ReplaceAll)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ReplaceAll)]
|
||||||
[[play](https://go.dev/play/p/CzqXMsuYUrx)]
|
[[play](https://go.dev/play/p/CzqXMsuYUrx)]
|
||||||
- **<big>Repeat</big>** : 创建一个切片,包含n个传入的item。
|
- **<big>Repeat</big>** : 创建一个切片,包含 n 个传入的 item。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Repeat)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Repeat)]
|
||||||
[[play](https://go.dev/play/p/1CbOmtgILUU)]
|
[[play](https://go.dev/play/p/1CbOmtgILUU)]
|
||||||
- **<big>Shuffle</big>** : 随机打乱切片中的元素顺序。
|
- **<big>Shuffle</big>** : 随机打乱切片中的元素顺序。
|
||||||
@@ -928,22 +965,26 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
[[play](https://go.dev/play/p/YHvhnWGU3Ge)]
|
[[play](https://go.dev/play/p/YHvhnWGU3Ge)]
|
||||||
- **<big>IsAscending</big>** : 检查切片元素是否按升序排列。
|
- **<big>IsAscending</big>** : 检查切片元素是否按升序排列。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsAscending)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsAscending)]
|
||||||
|
[[play](https://go.dev/play/p/9CtsFjet4SH)]
|
||||||
- **<big>IsDescending</big>** : 检查切片元素是否按降序排列。
|
- **<big>IsDescending</big>** : 检查切片元素是否按降序排列。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsDescending)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsDescending)]
|
||||||
|
[[play](https://go.dev/play/p/U_LljFXma14)]
|
||||||
- **<big>IsSorted</big>** : 检查切片元素是否是有序的(升序或降序)。
|
- **<big>IsSorted</big>** : 检查切片元素是否是有序的(升序或降序)。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsSorted)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsSorted)]
|
||||||
- **<big>IsSortedByKey</big>** : 通过iteratee函数,检查切片元素是否是有序的。
|
[[play](https://go.dev/play/p/nCE8wPLwSA-)]
|
||||||
|
- **<big>IsSortedByKey</big>** : 通过 iteratee 函数,检查切片元素是否是有序的。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsSortedByKey)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsSortedByKey)]
|
||||||
|
[[play](https://go.dev/play/p/tUoGB7DOHI4)]
|
||||||
- **<big>Sort</big>** : 对任何有序类型(数字或字符串)的切片进行排序,使用快速排序算法。
|
- **<big>Sort</big>** : 对任何有序类型(数字或字符串)的切片进行排序,使用快速排序算法。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Sort)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Sort)]
|
||||||
[[play](https://go.dev/play/p/V9AVjzf_4Fk)]
|
[[play](https://go.dev/play/p/V9AVjzf_4Fk)]
|
||||||
- **<big>SortBy</big>** : 按照less函数确定的升序规则对切片进行排序。排序不保证稳定性。
|
- **<big>SortBy</big>** : 按照 less 函数确定的升序规则对切片进行排序。排序不保证稳定性。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortBy)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortBy)]
|
||||||
[[play](https://go.dev/play/p/DAhLQSZEumm)]
|
[[play](https://go.dev/play/p/DAhLQSZEumm)]
|
||||||
- **<big>SortByField<sup>deprecated</sup></big>** : 按字段对结构切片进行排序。slice元素应为struct,字段类型应为int、uint、string或bool。
|
- **<big>SortByField<sup>deprecated</sup></big>** : 按字段对结构切片进行排序。slice 元素应为 struct,字段类型应为 int、uint、string 或 bool。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortByField)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortByField)]
|
||||||
[[play](https://go.dev/play/p/fU1prOBP9p1)]
|
[[play](https://go.dev/play/p/fU1prOBP9p1)]
|
||||||
- **<big>Some</big>** : 如果列表中的任何值通过谓词函数,则返回true。
|
- **<big>Some</big>** : 如果列表中的任何值通过谓词函数,则返回 true。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Some)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Some)]
|
||||||
[[play](https://go.dev/play/p/4pO9Xf9NDGS)]
|
[[play](https://go.dev/play/p/4pO9Xf9NDGS)]
|
||||||
- **<big>StringSlice<sup>deprecated</sup></big>** : 将接口切片转换为字符串切片。
|
- **<big>StringSlice<sup>deprecated</sup></big>** : 将接口切片转换为字符串切片。
|
||||||
@@ -961,7 +1002,7 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
- **<big>Unique</big>** : 删除切片中的重复元素。
|
- **<big>Unique</big>** : 删除切片中的重复元素。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Unique)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Unique)]
|
||||||
[[play](https://go.dev/play/p/AXw0R3ZTE6a)]
|
[[play](https://go.dev/play/p/AXw0R3ZTE6a)]
|
||||||
- **<big>UniqueBy</big>** : 对切片的每个元素调用iteratee函数,然后删除重复元素。
|
- **<big>UniqueBy</big>** : 对切片的每个元素调用 iteratee 函数,然后删除重复元素。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UniqueBy)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UniqueBy)]
|
||||||
[[play](https://go.dev/play/p/UR323iZLDpv)]
|
[[play](https://go.dev/play/p/UR323iZLDpv)]
|
||||||
- **<big>Union</big>** : 合并多个切片。
|
- **<big>Union</big>** : 合并多个切片。
|
||||||
@@ -976,10 +1017,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
- **<big>Without</big>** : 创建一个不包括所有给定值的切片。
|
- **<big>Without</big>** : 创建一个不包括所有给定值的切片。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Without)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Without)]
|
||||||
[[play](https://go.dev/play/p/bwhEXEypThg)]
|
[[play](https://go.dev/play/p/bwhEXEypThg)]
|
||||||
- **<big>KeyBy</big>** :将切片每个元素调用函数后转为map。
|
- **<big>KeyBy</big>** :将切片每个元素调用函数后转为 map。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#KeyBy)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#KeyBy)]
|
||||||
[[play](https://go.dev/play/p/uXod2LWD1Kg)]
|
[[play](https://go.dev/play/p/uXod2LWD1Kg)]
|
||||||
|
|
||||||
|
|
||||||
### 17. strutil 包含字符串处理的相关函数。
|
### 17. strutil 包含字符串处理的相关函数。
|
||||||
|
|
||||||
@@ -1022,6 +1062,9 @@ import "github.com/duke-git/lancet/v2/strutil"
|
|||||||
- **<big>UpperFirst</big>** : 将字符串的第一个字符转换为大写形式。
|
- **<big>UpperFirst</big>** : 将字符串的第一个字符转换为大写形式。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperFirst)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperFirst)]
|
||||||
[[play](https://go.dev/play/p/sBbBxRbs8MM)]
|
[[play](https://go.dev/play/p/sBbBxRbs8MM)]
|
||||||
|
- **<big>Pad</big>** : 如果字符串长度短于 size,则在左右两侧填充字符串。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Pad)]
|
||||||
|
[[play](https://go.dev/play/p/NzImQq-VF8q)]
|
||||||
- **<big>PadEnd</big>** : 如果字符串短于限制大小,则在右侧用给定字符填充字符串。 如果填充字符超出大小,它们将被截断。
|
- **<big>PadEnd</big>** : 如果字符串短于限制大小,则在右侧用给定字符填充字符串。 如果填充字符超出大小,它们将被截断。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadEnd)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadEnd)]
|
||||||
[[play](https://go.dev/play/p/9xP8rN0vz--)]
|
[[play](https://go.dev/play/p/9xP8rN0vz--)]
|
||||||
@@ -1049,6 +1092,13 @@ import "github.com/duke-git/lancet/v2/strutil"
|
|||||||
- **<big>Unwrap</big>** : 从另一个字符串中解开一个给定的字符串。 将更改源字符串。
|
- **<big>Unwrap</big>** : 从另一个字符串中解开一个给定的字符串。 将更改源字符串。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap)]
|
||||||
[[play](https://go.dev/play/p/Ec2q4BzCpG-)]
|
[[play](https://go.dev/play/p/Ec2q4BzCpG-)]
|
||||||
|
- **<big>SplitWords</big>** : 将字符串拆分为单词,只支持字母字符单词。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitWords)]
|
||||||
|
[[play](https://go.dev/play/p/KLiX4WiysMM)]
|
||||||
|
- **<big>WordCount</big>** : 返回有意义单词的数量,只支持字母字符单词。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#WordCount)]
|
||||||
|
[[play](https://go.dev/play/p/bj7_odx3vRf)]
|
||||||
|
|
||||||
|
|
||||||
### 18. system 包含 os, runtime, shell command 的相关函数。
|
### 18. system 包含 os, runtime, shell command 的相关函数。
|
||||||
|
|
||||||
@@ -1115,7 +1165,7 @@ import "github.com/duke-git/lancet/v2/validator"
|
|||||||
- **<big>IsAllLower</big>** : 验证字符串是否全是小写英文字母。
|
- **<big>IsAllLower</big>** : 验证字符串是否全是小写英文字母。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAllLower)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAllLower)]
|
||||||
[[play](https://go.dev/play/p/GjqCnOfV6cM)]
|
[[play](https://go.dev/play/p/GjqCnOfV6cM)]
|
||||||
- **<big>IsBase64</big>** : 验证字符串是否是base64编码。
|
- **<big>IsBase64</big>** : 验证字符串是否是 base64 编码。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsBase64)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsBase64)]
|
||||||
[[play](https://go.dev/play/p/sWHEySAt6hl)]
|
[[play](https://go.dev/play/p/sWHEySAt6hl)]
|
||||||
- **<big>IsChineseMobile</big>** : 验证字符串是否是中国手机号码。
|
- **<big>IsChineseMobile</big>** : 验证字符串是否是中国手机号码。
|
||||||
@@ -1130,7 +1180,7 @@ import "github.com/duke-git/lancet/v2/validator"
|
|||||||
- **<big>IsCreditCard</big>** : 验证字符串是否是信用卡号码。
|
- **<big>IsCreditCard</big>** : 验证字符串是否是信用卡号码。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsCreditCard)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsCreditCard)]
|
||||||
[[play](https://go.dev/play/p/sNwwL6B0-v4)]
|
[[play](https://go.dev/play/p/sNwwL6B0-v4)]
|
||||||
- **<big>IsDns</big>** : 验证字符串是否是有效dns。
|
- **<big>IsDns</big>** : 验证字符串是否是有效 dns。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsDns)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsDns)]
|
||||||
[[play](https://go.dev/play/p/jlYApVLLGTZ)]
|
[[play](https://go.dev/play/p/jlYApVLLGTZ)]
|
||||||
- **<big>IsEmail</big>** : 验证字符串是否是有效电子邮件地址。
|
- **<big>IsEmail</big>** : 验证字符串是否是有效电子邮件地址。
|
||||||
@@ -1145,7 +1195,7 @@ import "github.com/duke-git/lancet/v2/validator"
|
|||||||
- **<big>IsNumberStr</big>** : 验证字符串是否是可以转换为数字。
|
- **<big>IsNumberStr</big>** : 验证字符串是否是可以转换为数字。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsNumberStr)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsNumberStr)]
|
||||||
[[play](https://go.dev/play/p/LzaKocSV79u)]
|
[[play](https://go.dev/play/p/LzaKocSV79u)]
|
||||||
- **<big>IsJSON</big>** : 验证字符串是否是有效json。
|
- **<big>IsJSON</big>** : 验证字符串是否是有效 json。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsJSON)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsJSON)]
|
||||||
[[play](https://go.dev/play/p/sRS6c4K8jGk)]
|
[[play](https://go.dev/play/p/sRS6c4K8jGk)]
|
||||||
- **<big>IsRegexMatch</big>** : 验证字符串是否可以匹配正则表达式。
|
- **<big>IsRegexMatch</big>** : 验证字符串是否可以匹配正则表达式。
|
||||||
@@ -1154,19 +1204,19 @@ import "github.com/duke-git/lancet/v2/validator"
|
|||||||
- **<big>IsIntStr</big>** : 验证字符串是否是可以转换为整数。
|
- **<big>IsIntStr</big>** : 验证字符串是否是可以转换为整数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIntStr)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIntStr)]
|
||||||
[[play](https://go.dev/play/p/jQRtFv-a0Rk)]
|
[[play](https://go.dev/play/p/jQRtFv-a0Rk)]
|
||||||
- **<big>IsIp</big>** : 验证字符串是否是ip地址。
|
- **<big>IsIp</big>** : 验证字符串是否是 ip 地址。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIp)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIp)]
|
||||||
[[play](https://go.dev/play/p/FgcplDvmxoD)]
|
[[play](https://go.dev/play/p/FgcplDvmxoD)]
|
||||||
- **<big>IsIpV4</big>** : 验证字符串是否是ipv4地址。
|
- **<big>IsIpV4</big>** : 验证字符串是否是 ipv4 地址。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV4)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV4)]
|
||||||
[[play](https://go.dev/play/p/zBGT99EjaIu)]
|
[[play](https://go.dev/play/p/zBGT99EjaIu)]
|
||||||
- **<big>IsIpV6</big>** : 验证字符串是否是ipv6地址。
|
- **<big>IsIpV6</big>** : 验证字符串是否是 ipv6 地址。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV6)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV6)]
|
||||||
[[play](https://go.dev/play/p/AHA0r0AzIdC)]
|
[[play](https://go.dev/play/p/AHA0r0AzIdC)]
|
||||||
- **<big>IsStrongPassword</big>** : 验证字符串是否是强密码:(字母+数字+特殊字符)。
|
- **<big>IsStrongPassword</big>** : 验证字符串是否是强密码:(字母+数字+特殊字符)。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsStrongPassword)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsStrongPassword)]
|
||||||
[[play](https://go.dev/play/p/QHdVcSQ3uDg)]
|
[[play](https://go.dev/play/p/QHdVcSQ3uDg)]
|
||||||
- **<big>IsUrl</big>** : 验证字符串是否是url。
|
- **<big>IsUrl</big>** : 验证字符串是否是 url。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsUrl)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsUrl)]
|
||||||
[[play](https://go.dev/play/p/pbJGa7F98Ka)]
|
[[play](https://go.dev/play/p/pbJGa7F98Ka)]
|
||||||
- **<big>IsWeakPassword</big>** : 验证字符串是否是弱密码(只包含字母+数字)。
|
- **<big>IsWeakPassword</big>** : 验证字符串是否是弱密码(只包含字母+数字)。
|
||||||
@@ -1175,10 +1225,9 @@ import "github.com/duke-git/lancet/v2/validator"
|
|||||||
- **<big>IsZeroValue</big>** : 判断传入的参数值是否为零值。
|
- **<big>IsZeroValue</big>** : 判断传入的参数值是否为零值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsZeroValue)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsZeroValue)]
|
||||||
[[play](https://go.dev/play/p/UMrwaDCi_t4)]
|
[[play](https://go.dev/play/p/UMrwaDCi_t4)]
|
||||||
- **<big>IsGBK</big>** : 检查数据编码是否为gbk(汉字内部代码扩展规范)。
|
- **<big>IsGBK</big>** : 检查数据编码是否为 gbk(汉字内部代码扩展规范)。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsGBK)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsGBK)]
|
||||||
[[play](https://go.dev/play/p/E2nt3unlmzP)]
|
[[play](https://go.dev/play/p/E2nt3unlmzP)]
|
||||||
|
|
||||||
|
|
||||||
### 20. xerror 包实现一些错误处理函数
|
### 20. xerror 包实现一些错误处理函数
|
||||||
|
|
||||||
@@ -1188,34 +1237,45 @@ import "github.com/duke-git/lancet/v2/xerror"
|
|||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
|
|
||||||
- **<big>New</big>** : 创建XError对象实例。
|
- **<big>New</big>** : 创建 XError 对象实例。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#New)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#New)]
|
||||||
- **<big>Wrap</big>** : 根据error对象创建XError对象实例,可添加message。
|
[[play](https://go.dev/play/p/w4oWZts7q7f)]
|
||||||
|
- **<big>Wrap</big>** : 根据 error 对象创建 XError 对象实例,可添加 message。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Wrap)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Wrap)]
|
||||||
- **<big>Unwrap</big>** : 从error对象中解构出XError。
|
[[play](https://go.dev/play/p/5385qT2dCi4)]
|
||||||
|
- **<big>Unwrap</big>** : 从 error 对象中解构出 XError。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Unwrap)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Unwrap)]
|
||||||
- **<big>XError_Wrap</big>** : 创建新的XError对象并将消息和id复制到新的对象中。
|
[[play](https://go.dev/play/p/LKMLep723tu)]
|
||||||
|
- **<big>XError_Wrap</big>** : 创建新的 XError 对象并将消息和 id 复制到新的对象中。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Wrap)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Wrap)]
|
||||||
- **<big>XError_Unwrap</big>** : 解构XEerror为error对象。适配github.com/pkg/errors。
|
[[play](https://go.dev/play/p/5385qT2dCi4)]
|
||||||
|
- **<big>XError_Unwrap</big>** : 解构 XEerror 为 error 对象。适配 github.com/pkg/errors。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Unwrap)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Unwrap)]
|
||||||
- **<big>XError_With</big>** : 添加与XError对象的键和值。
|
[[play](https://go.dev/play/p/VUXJ8BST4c6)]
|
||||||
|
- **<big>XError_With</big>** : 添加与 XError 对象的键和值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_With)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_With)]
|
||||||
- **<big>XError_Id</big>** : 设置XError对象的id。
|
[[play](https://go.dev/play/p/ow8UISXX_Dp)]
|
||||||
|
- **<big>XError_Id</big>** : 设置 XError 对象的 id。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Id)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Id)]
|
||||||
- **<big>XError_Is</big>** : 检查目标error是否为XError,两个错误中的error.id是否匹配。
|
[[play](https://go.dev/play/p/X6HBlsy58U9)]
|
||||||
|
- **<big>XError_Is</big>** : 检查目标 error 是否为 XError,两个错误中的 error.id 是否匹配。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Is)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Is)]
|
||||||
- **<big>XError_Values</big>** : 返回由With设置的键和值的映射。将合并所有XError键和值。
|
[[play](https://go.dev/play/p/X6HBlsy58U9)]
|
||||||
|
- **<big>XError_Values</big>** : 返回由 With 设置的键和值的映射。将合并所有 XError 键和值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Values)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Values)]
|
||||||
- **<big>XError_StackTrace</big>** : 返回与pkg/error兼容的堆栈信息。
|
[[play](https://go.dev/play/p/ow8UISXX_Dp)]
|
||||||
|
- **<big>XError_StackTrace</big>** : 返回与 pkg/error 兼容的堆栈信息。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_StackTrace)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_StackTrace)]
|
||||||
- **<big>XError_Info</big>** : 返回可打印的XError对象信息。
|
[[play](https://go.dev/play/p/6FAvSQpa7pc)]
|
||||||
|
- **<big>XError_Info</big>** : 返回可打印的 XError 对象信息。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Info)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Info)]
|
||||||
- **<big>XError_Error</big>** : 实现标准库的error接口。
|
[[play](https://go.dev/play/p/1ZX0ME1F-Jb)]
|
||||||
|
- **<big>XError_Error</big>** : 实现标准库的 error 接口。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Error)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Error)]
|
||||||
- **<big>TryUnwrap</big>** : 检查error, 如果err为nil则展开,则它返回一个有效值,如果err不是nil则Unwrap使用err发生panic。
|
[[play](https://go.dev/play/p/w4oWZts7q7f)]
|
||||||
|
- **<big>TryUnwrap</big>** : 检查 error, 如果 err 为 nil 则展开,则它返回一个有效值,如果 err 不是 nil 则 Unwrap 使用 err 发生 panic。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#TryUnwrap)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#TryUnwrap)]
|
||||||
[[play](https://go.dev/play/p/w84d7Mb3Afk)]
|
[[play](https://go.dev/play/p/acyZVkNZEeW)]
|
||||||
|
|
||||||
|
|
||||||
## 如何贡献代码
|
## 如何贡献代码
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,11 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/structutil"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -234,31 +235,7 @@ func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K
|
|||||||
// map key is specified same as struct field tag `json` value.
|
// map key is specified same as struct field tag `json` value.
|
||||||
// Play: https://go.dev/play/p/KYGYJqNUBOI
|
// Play: https://go.dev/play/p/KYGYJqNUBOI
|
||||||
func StructToMap(value any) (map[string]any, error) {
|
func StructToMap(value any) (map[string]any, error) {
|
||||||
v := reflect.ValueOf(value)
|
return structutil.ToMap(value)
|
||||||
t := reflect.TypeOf(value)
|
|
||||||
|
|
||||||
if t.Kind() == reflect.Ptr {
|
|
||||||
t = t.Elem()
|
|
||||||
}
|
|
||||||
if t.Kind() != reflect.Struct {
|
|
||||||
return nil, fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
result := make(map[string]any)
|
|
||||||
|
|
||||||
fieldNum := t.NumField()
|
|
||||||
pattern := `^[A-Z]`
|
|
||||||
regex := regexp.MustCompile(pattern)
|
|
||||||
for i := 0; i < fieldNum; i++ {
|
|
||||||
name := t.Field(i).Name
|
|
||||||
tag := t.Field(i).Tag.Get("json")
|
|
||||||
if regex.MatchString(name) && tag != "" {
|
|
||||||
//result[name] = v.Field(i).Interface()
|
|
||||||
result[tag] = v.Field(i).Interface()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapToSlice convert map to slice based on iteratee function.
|
// MapToSlice convert map to slice based on iteratee function.
|
||||||
@@ -327,7 +304,7 @@ func DecodeByte(data []byte, target any) error {
|
|||||||
|
|
||||||
// DeepClone creates a deep copy of passed item.
|
// DeepClone creates a deep copy of passed item.
|
||||||
// can't clone unexported field of struct
|
// can't clone unexported field of struct
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/j4DP5dquxnk
|
||||||
func DeepClone[T any](src T) T {
|
func DeepClone[T any](src T) T {
|
||||||
c := cloner{
|
c := cloner{
|
||||||
ptrs: map[reflect.Type]map[uintptr]reflect.Value{},
|
ptrs: map[reflect.Type]map[uintptr]reflect.Value{},
|
||||||
@@ -340,3 +317,46 @@ func DeepClone[T any](src T) T {
|
|||||||
|
|
||||||
return result.Interface().(T)
|
return result.Interface().(T)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CopyProperties copies each field from the source into the destination. It recursively copies struct pointers and interfaces that contain struct pointers.
|
||||||
|
// Play: https://go.dev/play/p/FOVY3XJL-6B
|
||||||
|
func CopyProperties[T, U any](dst T, src U) (err error) {
|
||||||
|
defer func() {
|
||||||
|
if e := recover(); e != nil {
|
||||||
|
err = fmt.Errorf("%v", e)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
dstType, dstValue := reflect.TypeOf(dst), reflect.ValueOf(dst)
|
||||||
|
srcType, srcValue := reflect.TypeOf(src), reflect.ValueOf(src)
|
||||||
|
|
||||||
|
if dstType.Kind() != reflect.Ptr || dstType.Elem().Kind() != reflect.Struct {
|
||||||
|
return errors.New("CopyProperties: param dst should be struct pointer")
|
||||||
|
}
|
||||||
|
|
||||||
|
if srcType.Kind() == reflect.Ptr {
|
||||||
|
srcType, srcValue = srcType.Elem(), srcValue.Elem()
|
||||||
|
}
|
||||||
|
if srcType.Kind() != reflect.Struct {
|
||||||
|
return errors.New("CopyProperties: param src should be a struct or struct pointer")
|
||||||
|
}
|
||||||
|
|
||||||
|
dstType, dstValue = dstType.Elem(), dstValue.Elem()
|
||||||
|
|
||||||
|
propertyNums := dstType.NumField()
|
||||||
|
|
||||||
|
for i := 0; i < propertyNums; i++ {
|
||||||
|
property := dstType.Field(i)
|
||||||
|
propertyValue := srcValue.FieldByName(property.Name)
|
||||||
|
|
||||||
|
if !propertyValue.IsValid() || property.Type != propertyValue.Type() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if dstValue.Field(i).CanSet() {
|
||||||
|
dstValue.Field(i).Set(propertyValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -255,12 +255,12 @@ func ExampleDecodeByte() {
|
|||||||
|
|
||||||
func ExampleDeepClone() {
|
func ExampleDeepClone() {
|
||||||
type Struct struct {
|
type Struct struct {
|
||||||
Str string
|
Str string
|
||||||
Int int
|
Int int
|
||||||
Float float64
|
Float float64
|
||||||
Bool bool
|
Bool bool
|
||||||
Nil interface{}
|
Nil interface{}
|
||||||
unexported string
|
// unexported string
|
||||||
}
|
}
|
||||||
|
|
||||||
cases := []interface{}{
|
cases := []interface{}{
|
||||||
@@ -293,5 +293,53 @@ func ExampleDeepClone() {
|
|||||||
// 1 false
|
// 1 false
|
||||||
// 0.1 false
|
// 0.1 false
|
||||||
// map[a:1 b:2] false
|
// map[a:1 b:2] false
|
||||||
// &{test 1 0.1 true <nil> } false
|
// &{test 1 0.1 true <nil>} false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleCopyProperties() {
|
||||||
|
type Address struct {
|
||||||
|
Country string
|
||||||
|
ZipCode string
|
||||||
|
}
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
Role string
|
||||||
|
Addr Address
|
||||||
|
Hobbys []string
|
||||||
|
salary int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Employee struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
Role string
|
||||||
|
Addr Address
|
||||||
|
Hobbys []string
|
||||||
|
salary int
|
||||||
|
}
|
||||||
|
|
||||||
|
user := User{Name: "user001", Age: 10, Role: "Admin", Addr: Address{Country: "CN", ZipCode: "001"}, Hobbys: []string{"a", "b"}, salary: 1000}
|
||||||
|
|
||||||
|
employee1 := Employee{}
|
||||||
|
err := CopyProperties(&employee1, &user)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
employee2 := Employee{Name: "employee001", Age: 20, Role: "User",
|
||||||
|
Addr: Address{Country: "UK", ZipCode: "002"}, salary: 500}
|
||||||
|
|
||||||
|
err = CopyProperties(&employee2, &user)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(employee1)
|
||||||
|
fmt.Println(employee2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {user001 10 Admin {CN 001} [a b] 0}
|
||||||
|
// {user001 10 Admin {CN 001} [a b] 500}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,18 +180,36 @@ func TestToMap(t *testing.T) {
|
|||||||
func TestStructToMap(t *testing.T) {
|
func TestStructToMap(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestStructToMap")
|
assert := internal.NewAssert(t, "TestStructToMap")
|
||||||
|
|
||||||
type People struct {
|
t.Run("StructToMap", func(_ *testing.T) {
|
||||||
Name string `json:"name"`
|
type People struct {
|
||||||
age int
|
Name string `json:"name"`
|
||||||
}
|
age int
|
||||||
p := People{
|
}
|
||||||
"test",
|
p := People{
|
||||||
100,
|
"test",
|
||||||
}
|
100,
|
||||||
pm, _ := StructToMap(p)
|
}
|
||||||
|
pm, _ := StructToMap(p)
|
||||||
|
var expected = map[string]any{"name": "test"}
|
||||||
|
assert.Equal(expected, pm)
|
||||||
|
})
|
||||||
|
|
||||||
expected := map[string]any{"name": "test"}
|
t.Run("StructToMapWithJsonAttr", func(_ *testing.T) {
|
||||||
assert.Equal(expected, pm)
|
type People struct {
|
||||||
|
Name string `json:"name,omitempty"` // json tag with attribute
|
||||||
|
Phone string `json:"phone"` // json tag without attribute
|
||||||
|
Sex string `json:"-"` // ignore
|
||||||
|
age int // no tag
|
||||||
|
}
|
||||||
|
p := People{
|
||||||
|
Phone: "1111",
|
||||||
|
Sex: "male",
|
||||||
|
age: 100,
|
||||||
|
}
|
||||||
|
pm, _ := StructToMap(p)
|
||||||
|
var expected = map[string]any{"phone": "1111"}
|
||||||
|
assert.Equal(expected, pm)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMapToSlice(t *testing.T) {
|
func TestMapToSlice(t *testing.T) {
|
||||||
@@ -259,12 +277,12 @@ func TestDeepClone(t *testing.T) {
|
|||||||
// assert := internal.NewAssert(t, "TestDeepClone")
|
// assert := internal.NewAssert(t, "TestDeepClone")
|
||||||
|
|
||||||
type Struct struct {
|
type Struct struct {
|
||||||
Str string
|
Str string
|
||||||
Int int
|
Int int
|
||||||
Float float64
|
Float float64
|
||||||
Bool bool
|
Bool bool
|
||||||
Nil interface{}
|
Nil interface{}
|
||||||
unexported string
|
// unexported string
|
||||||
}
|
}
|
||||||
|
|
||||||
cases := []interface{}{
|
cases := []interface{}{
|
||||||
@@ -298,3 +316,53 @@ func TestDeepClone(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCopyProperties(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestCopyProperties")
|
||||||
|
|
||||||
|
type Address struct {
|
||||||
|
Country string
|
||||||
|
ZipCode string
|
||||||
|
}
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
Role string
|
||||||
|
Addr Address
|
||||||
|
Hobbys []string
|
||||||
|
salary int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Employee struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
Role string
|
||||||
|
Addr Address
|
||||||
|
Hobbys []string
|
||||||
|
salary int
|
||||||
|
}
|
||||||
|
|
||||||
|
user := User{Name: "user001", Age: 10, Role: "Admin", Addr: Address{Country: "CN", ZipCode: "001"}, Hobbys: []string{"a", "b"}, salary: 1000}
|
||||||
|
|
||||||
|
employee1 := Employee{}
|
||||||
|
|
||||||
|
err := CopyProperties(&employee1, &user)
|
||||||
|
|
||||||
|
assert.IsNil(err)
|
||||||
|
assert.Equal("user001", employee1.Name)
|
||||||
|
assert.Equal("Admin", employee1.Role)
|
||||||
|
assert.Equal("CN", employee1.Addr.Country)
|
||||||
|
assert.Equal(0, employee1.salary)
|
||||||
|
|
||||||
|
employee2 := Employee{Name: "employee001", Age: 20, Role: "User",
|
||||||
|
Addr: Address{Country: "UK", ZipCode: "002"}, salary: 500}
|
||||||
|
|
||||||
|
err = CopyProperties(&employee2, &user)
|
||||||
|
|
||||||
|
assert.IsNil(err)
|
||||||
|
assert.Equal("user001", employee2.Name)
|
||||||
|
assert.Equal("Admin", employee2.Role)
|
||||||
|
assert.Equal("CN", employee2.Addr.Country)
|
||||||
|
assert.Equal(500, employee2.salary)
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ type mapNode struct {
|
|||||||
next *mapNode
|
next *mapNode
|
||||||
}
|
}
|
||||||
|
|
||||||
//HashMap implements a hash map
|
// HashMap implements a hash map
|
||||||
type HashMap struct {
|
type HashMap struct {
|
||||||
capacity uint64
|
capacity uint64
|
||||||
size uint64
|
size uint64
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import (
|
|||||||
- [EncodeByte](#EncodeByte)
|
- [EncodeByte](#EncodeByte)
|
||||||
- [DecodeByte](#DecodeByte)
|
- [DecodeByte](#DecodeByte)
|
||||||
- [DeepClone](#DeepClone)
|
- [DeepClone](#DeepClone)
|
||||||
|
- [CopyProperties](#CopyProperties)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -651,44 +652,108 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
type Struct struct {
|
type Struct struct {
|
||||||
Str string
|
Str string
|
||||||
Int int
|
Int int
|
||||||
Float float64
|
Float float64
|
||||||
Bool bool
|
Bool bool
|
||||||
Nil interface{}
|
Nil interface{}
|
||||||
unexported string
|
unexported string
|
||||||
}
|
}
|
||||||
|
|
||||||
cases := []interface{}{
|
cases := []interface{}{
|
||||||
true,
|
true,
|
||||||
1,
|
1,
|
||||||
0.1,
|
0.1,
|
||||||
map[string]int{
|
map[string]int{
|
||||||
"a": 1,
|
"a": 1,
|
||||||
"b": 2,
|
"b": 2,
|
||||||
},
|
},
|
||||||
&Struct{
|
&Struct{
|
||||||
Str: "test",
|
Str: "test",
|
||||||
Int: 1,
|
Int: 1,
|
||||||
Float: 0.1,
|
Float: 0.1,
|
||||||
Bool: true,
|
Bool: true,
|
||||||
Nil: nil,
|
Nil: nil,
|
||||||
// unexported: "can't be cloned",
|
// unexported: "can't be cloned",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, item := range cases {
|
for _, item := range cases {
|
||||||
cloned := convertor.DeepClone(item)
|
cloned := convertor.DeepClone(item)
|
||||||
|
|
||||||
isPointerEqual := &cloned == &item
|
isPointerEqual := &cloned == &item
|
||||||
fmt.Println(cloned, isPointerEqual)
|
fmt.Println(cloned, isPointerEqual)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// true false
|
// true false
|
||||||
// 1 false
|
// 1 false
|
||||||
// 0.1 false
|
// 0.1 false
|
||||||
// map[a:1 b:2] false
|
// map[a:1 b:2] false
|
||||||
// &{test 1 0.1 true <nil> } false
|
// &{test 1 0.1 true <nil> } false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="CopyProperties">CopyProperties</span>
|
||||||
|
|
||||||
|
<p>Copies each field from the source struct into the destination struct.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func CopyProperties[T, U any](dst T, src U) (err error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type Address struct {
|
||||||
|
Country string
|
||||||
|
ZipCode string
|
||||||
|
}
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
Role string
|
||||||
|
Addr Address
|
||||||
|
Hobbys []string
|
||||||
|
salary int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Employee struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
Role string
|
||||||
|
Addr Address
|
||||||
|
Hobbys []string
|
||||||
|
salary int
|
||||||
|
}
|
||||||
|
|
||||||
|
user := User{Name: "user001", Age: 10, Role: "Admin", Addr: Address{Country: "CN", ZipCode: "001"}, Hobbys: []string{"a", "b"}, salary: 1000}
|
||||||
|
|
||||||
|
employee1 := Employee{}
|
||||||
|
CopyProperties(&employee1, &user)
|
||||||
|
|
||||||
|
employee2 := Employee{Name: "employee001", Age: 20, Role: "User",
|
||||||
|
Addr: Address{Country: "UK", ZipCode: "002"}, salary: 500}
|
||||||
|
|
||||||
|
CopyProperties(&employee2, &user)
|
||||||
|
|
||||||
|
fmt.Println(employee1)
|
||||||
|
fmt.Println(employee2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {user001 10 Admin {CN 001} [a b] 0}
|
||||||
|
// {user001 10 Admin {CN 001} [a b] 500}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -39,6 +39,8 @@ import (
|
|||||||
- [EncodeByte](#EncodeByte)
|
- [EncodeByte](#EncodeByte)
|
||||||
- [DecodeByte](#DecodeByte)
|
- [DecodeByte](#DecodeByte)
|
||||||
- [DeepClone](#DeepClone)
|
- [DeepClone](#DeepClone)
|
||||||
|
- [CopyProperties](#CopyProperties)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -650,44 +652,107 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
type Struct struct {
|
type Struct struct {
|
||||||
Str string
|
Str string
|
||||||
Int int
|
Int int
|
||||||
Float float64
|
Float float64
|
||||||
Bool bool
|
Bool bool
|
||||||
Nil interface{}
|
Nil interface{}
|
||||||
unexported string
|
unexported string
|
||||||
}
|
}
|
||||||
|
|
||||||
cases := []interface{}{
|
cases := []interface{}{
|
||||||
true,
|
true,
|
||||||
1,
|
1,
|
||||||
0.1,
|
0.1,
|
||||||
map[string]int{
|
map[string]int{
|
||||||
"a": 1,
|
"a": 1,
|
||||||
"b": 2,
|
"b": 2,
|
||||||
},
|
},
|
||||||
&Struct{
|
&Struct{
|
||||||
Str: "test",
|
Str: "test",
|
||||||
Int: 1,
|
Int: 1,
|
||||||
Float: 0.1,
|
Float: 0.1,
|
||||||
Bool: true,
|
Bool: true,
|
||||||
Nil: nil,
|
Nil: nil,
|
||||||
// unexported: "can't be cloned",
|
// unexported: "can't be cloned",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, item := range cases {
|
for _, item := range cases {
|
||||||
cloned := convertor.DeepClone(item)
|
cloned := convertor.DeepClone(item)
|
||||||
|
|
||||||
isPointerEqual := &cloned == &item
|
isPointerEqual := &cloned == &item
|
||||||
fmt.Println(cloned, isPointerEqual)
|
fmt.Println(cloned, isPointerEqual)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// true false
|
// true false
|
||||||
// 1 false
|
// 1 false
|
||||||
// 0.1 false
|
// 0.1 false
|
||||||
// map[a:1 b:2] false
|
// map[a:1 b:2] false
|
||||||
// &{test 1 0.1 true <nil> } false
|
// &{test 1 0.1 true <nil> } false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="CopyProperties">CopyProperties</span>
|
||||||
|
|
||||||
|
<p>拷贝不同结构体之间的同名字段。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func CopyProperties[T, U any](dst T, src U) (err error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type Address struct {
|
||||||
|
Country string
|
||||||
|
ZipCode string
|
||||||
|
}
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
Role string
|
||||||
|
Addr Address
|
||||||
|
Hobbys []string
|
||||||
|
salary int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Employee struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
Role string
|
||||||
|
Addr Address
|
||||||
|
Hobbys []string
|
||||||
|
salary int
|
||||||
|
}
|
||||||
|
|
||||||
|
user := User{Name: "user001", Age: 10, Role: "Admin", Addr: Address{Country: "CN", ZipCode: "001"}, Hobbys: []string{"a", "b"}, salary: 1000}
|
||||||
|
|
||||||
|
employee1 := Employee{}
|
||||||
|
CopyProperties(&employee1, &user)
|
||||||
|
|
||||||
|
employee2 := Employee{Name: "employee001", Age: 20, Role: "User",
|
||||||
|
Addr: Address{Country: "UK", ZipCode: "002"}, salary: 500}
|
||||||
|
|
||||||
|
CopyProperties(&employee2, &user)
|
||||||
|
|
||||||
|
fmt.Println(employee1)
|
||||||
|
fmt.Println(employee2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {user001 10 Admin {CN 001} [a b] 0}
|
||||||
|
// {user001 10 Admin {CN 001} [a b] 500}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -29,6 +29,7 @@ import (
|
|||||||
- [Compose](#Compose)
|
- [Compose](#Compose)
|
||||||
- [Debounced](#Debounced)
|
- [Debounced](#Debounced)
|
||||||
- [Delay](#Delay)
|
- [Delay](#Delay)
|
||||||
|
- [Schedule](#Schedule)
|
||||||
- [Pipeline](#Pipeline)
|
- [Pipeline](#Pipeline)
|
||||||
- [Watcher](#Watcher)
|
- [Watcher](#Watcher)
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import (
|
|||||||
- [Compose](#Compose)
|
- [Compose](#Compose)
|
||||||
- [Debounced](#Debounced)
|
- [Debounced](#Debounced)
|
||||||
- [Delay](#Delay)
|
- [Delay](#Delay)
|
||||||
|
- [Schedule](#Schedule)
|
||||||
- [Pipeline](#Pipeline)
|
- [Pipeline](#Pipeline)
|
||||||
- [Watcher](#Watcher)
|
- [Watcher](#Watcher)
|
||||||
|
|
||||||
@@ -206,7 +207,7 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
count := 0
|
count := 0
|
||||||
|
|
||||||
add := func() {
|
add := func() {
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
|
|||||||
509
docs/maputil.md
509
docs/maputil.md
@@ -24,11 +24,23 @@ import (
|
|||||||
|
|
||||||
- [ForEach](#ForEach)
|
- [ForEach](#ForEach)
|
||||||
- [Filter](#Filter)
|
- [Filter](#Filter)
|
||||||
|
- [FilterByKeys](#FilterByKeys)
|
||||||
|
- [FilterByValues](#FilterByValues)
|
||||||
|
- [OmitBy](#OmitBy)
|
||||||
|
- [OmitByKeys](#OmitByKeys)
|
||||||
|
- [OmitByValues](#OmitByValues)
|
||||||
- [Intersect](#Intersect)
|
- [Intersect](#Intersect)
|
||||||
- [Keys](#Keys)
|
- [Keys](#Keys)
|
||||||
|
- [Values](#Values)
|
||||||
|
- [KeysBy](#KeysBy)
|
||||||
|
- [ValuesBy](#ValuesBy)
|
||||||
|
- [MapKeys](#MapKeys)
|
||||||
|
- [MapValues](#MapValues)
|
||||||
|
- [Entries](#Entries)
|
||||||
|
- [FromEntries](#FromEntries)
|
||||||
|
- [Transform](#Transform)
|
||||||
- [Merge](#Merge)
|
- [Merge](#Merge)
|
||||||
- [Minus](#Minus)
|
- [Minus](#Minus)
|
||||||
- [Values](#Values)
|
|
||||||
- [IsDisjoint](#IsDisjoint)
|
- [IsDisjoint](#IsDisjoint)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
@@ -121,6 +133,205 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="FilterByKeys">FilterByKeys</span>
|
||||||
|
|
||||||
|
<p>Iterates over map, return a new map whose keys are all given keys.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FilterByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.FilterByKeys(m, []string{"a", "b"})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 b:2]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="FilterByValues">FilterByValues</span>
|
||||||
|
|
||||||
|
<p>Iterates over map, return a new map whose values are all given values.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FilterByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.FilterByValues(m, []int{3, 4})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[c:3 d:4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="OmitBy">OmitBy</span>
|
||||||
|
|
||||||
|
<p>OmitBy is the opposite of Filter, removes all the map elements for which the predicate function returns true.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func OmitBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
isEven := func(_ string, value int) bool {
|
||||||
|
return value%2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.OmitBy(m, isEven)
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 c:3 e:5]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="OmitByKeys">OmitByKeys</span>
|
||||||
|
|
||||||
|
<p>The opposite of FilterByKeys, extracts all the map elements which keys are not omitted.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func OmitByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.OmitByKeys(m, []string{"a", "b"})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[c:3 d:4 e:5]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="OmitByValues">OmitByValues</span>
|
||||||
|
|
||||||
|
<p>The opposite of FilterByValues. remov all elements whose value are in the give slice.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func OmitByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.OmitByValues(m, []int{4, 5})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 b:2 c:3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="Intersect">Intersect</span>
|
### <span id="Intersect">Intersect</span>
|
||||||
|
|
||||||
<p>Iterates over maps, return a new map of key and value pairs in all given maps.</p>
|
<p>Iterates over maps, return a new map of key and value pairs in all given maps.</p>
|
||||||
@@ -193,6 +404,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -313,6 +525,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -335,6 +548,300 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="KeysBy">KeysBy</span>
|
||||||
|
|
||||||
|
<p>Creates a slice whose element is the result of function mapper invoked by every map's key.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func KeysBy[K comparable, V any, T any](m map[K]V, mapper func(item K) T) []T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "a",
|
||||||
|
3: "b",
|
||||||
|
}
|
||||||
|
|
||||||
|
keys := maputil.KeysBy(m, func(n int) int {
|
||||||
|
return n + 1
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Ints(keys)
|
||||||
|
|
||||||
|
fmt.Println(keys)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ValuesBy">ValuesBy</span>
|
||||||
|
|
||||||
|
<p>Creates a slice whose element is the result of function mapper invoked by every map's value.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ValuesBy[K comparable, V any, T any](m map[K]V, mapper func(item V) T) []T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "b",
|
||||||
|
3: "c",
|
||||||
|
}
|
||||||
|
values := maputil.ValuesBy(m, func(v string) string {
|
||||||
|
switch v {
|
||||||
|
case "a":
|
||||||
|
return "a-1"
|
||||||
|
case "b":
|
||||||
|
return "b-2"
|
||||||
|
case "c":
|
||||||
|
return "c-3"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Strings(values)
|
||||||
|
|
||||||
|
fmt.Println(values)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [a-1 b-2 c-3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="MapKeys">MapKeys</span>
|
||||||
|
|
||||||
|
<p>Transforms a map to other type map by manipulating it's keys.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func MapKeys[K comparable, V any, T comparable](m map[K]V, iteratee func(key K, value V) T) map[T]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "b",
|
||||||
|
3: "c",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.MapKeys(m, func(k int, _ string) string {
|
||||||
|
return strconv.Itoa(k)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[1:a 2:b 3:c]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="MapValues">MapValues</span>
|
||||||
|
|
||||||
|
<p>Transforms a map to other type map by manipulating it's values.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func MapValues[K comparable, V any, T any](m map[K]V, iteratee func(key K, value V) T) map[K]T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "b",
|
||||||
|
3: "c",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.MapValues(m, func(k int, v string) string {
|
||||||
|
return v + strconv.Itoa(k)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[1:a1 2:b2 3:c3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="Entry">Entry</span>
|
||||||
|
|
||||||
|
<p>Transforms a map into array of key/value pairs.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Entry[K comparable, V any] struct {
|
||||||
|
Key K
|
||||||
|
Value V
|
||||||
|
}
|
||||||
|
func Entries[K comparable, V any](m map[K]V) []Entry[K, V]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.Entries(m)
|
||||||
|
|
||||||
|
sort.Slice(result, func(i, j int) bool {
|
||||||
|
return result[i].Value < result[j].Value
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [{a 1} {b 2} {c 3}]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="FromEntries">FromEntries</span>
|
||||||
|
|
||||||
|
<p>Creates a map based on a slice of key/value pairs.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Entry[K comparable, V any] struct {
|
||||||
|
Key K
|
||||||
|
Value V
|
||||||
|
}
|
||||||
|
func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result := maputil.FromEntries([]Entry[string, int]{
|
||||||
|
{Key: "a", Value: 1},
|
||||||
|
{Key: "b", Value: 2},
|
||||||
|
{Key: "c", Value: 3},
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 b:2 c:3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Transform">Transform</span>
|
||||||
|
|
||||||
|
<p>Transform a map to another type map.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Transform[K1 comparable, V1 any, K2 comparable, V2 any](m map[K1]V1, iteratee func(key K1, value V1) (K2, V2)) map[K2]V2
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := Transform(m, func(k string, v int) (string, string) {
|
||||||
|
return k, strconv.Itoa(v)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 b:2 c:3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="IsDisjoint">IsDisjoint</span>
|
### <span id="IsDisjoint">IsDisjoint</span>
|
||||||
|
|
||||||
<p>Checks two maps are disjoint if they have no keys in common</p>
|
<p>Checks two maps are disjoint if they have no keys in common</p>
|
||||||
|
|||||||
@@ -24,11 +24,23 @@ import (
|
|||||||
|
|
||||||
- [ForEach](#ForEach)
|
- [ForEach](#ForEach)
|
||||||
- [Filter](#Filter)
|
- [Filter](#Filter)
|
||||||
|
- [FilterByKeys](#FilterByKeys)
|
||||||
|
- [FilterByValues](#FilterByValues)
|
||||||
|
- [OmitBy](#OmitBy)
|
||||||
|
- [OmitByKeys](#OmitByKeys)
|
||||||
|
- [OmitByValues](#OmitByValues)
|
||||||
- [Intersect](#Intersect)
|
- [Intersect](#Intersect)
|
||||||
- [Keys](#Keys)
|
- [Keys](#Keys)
|
||||||
|
- [Values](#Values)
|
||||||
|
- [KeysBy](#KeysBy)
|
||||||
|
- [ValuesBy](#ValuesBy)
|
||||||
|
- [MapKeys](#MapKeys)
|
||||||
|
- [MapValues](#MapValues)
|
||||||
|
- [Entries](#Entries)
|
||||||
|
- [FromEntries](#FromEntries)
|
||||||
|
- [Transform](#Transform)
|
||||||
- [Merge](#Merge)
|
- [Merge](#Merge)
|
||||||
- [Minus](#Minus)
|
- [Minus](#Minus)
|
||||||
- [Values](#Values)
|
|
||||||
- [IsDisjoint](#IsDisjoint)
|
- [IsDisjoint](#IsDisjoint)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
@@ -78,7 +90,7 @@ func main() {
|
|||||||
|
|
||||||
### <span id="Filter">Filter</span>
|
### <span id="Filter">Filter</span>
|
||||||
|
|
||||||
<p>迭代map中的每对key和value, 返回符合predicate函数的key, value</p>
|
<p>迭代map中的每对key和value, 返回符合predicate函数的key, value。</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
@@ -121,6 +133,203 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="FilterByKeys">FilterByKeys</span>
|
||||||
|
|
||||||
|
<p>迭代map, 返回一个新map,其key都是给定的key值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FilterByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.FilterByKeys(m, []string{"a", "b"})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 b:2]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="FilterByValues">FilterByValues</span>
|
||||||
|
|
||||||
|
<p>迭代map, 返回一个新map,其value都是给定的value值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FilterByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.FilterByValues(m, []int{3, 4})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[c:3 d:4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="OmitBy">OmitBy</span>
|
||||||
|
|
||||||
|
<p>Filter的反向操作, 迭代map中的每对key和value, 删除符合predicate函数的key, value, 返回新map。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func OmitBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
isEven := func(_ string, value int) bool {
|
||||||
|
return value%2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.OmitBy(m, isEven)
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 c:3 e:5]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="OmitByKeys">OmitByKeys</span>
|
||||||
|
|
||||||
|
<p>FilterByKeys的反向操作, 迭代map, 返回一个新map,其key不包括给定的key值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func OmitByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.OmitByKeys(m, []string{"a", "b"})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[c:3 d:4 e:5]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="OmitByValues">OmitByValues</span>
|
||||||
|
|
||||||
|
<p>FilterByValues的反向操作, 迭代map, 返回一个新map,其value不包括给定的value值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func OmitByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.OmitByValues(m, []int{4, 5})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 b:2 c:3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="Intersect">Intersect</span>
|
### <span id="Intersect">Intersect</span>
|
||||||
|
|
||||||
<p>多个map的交集操作</p>
|
<p>多个map的交集操作</p>
|
||||||
@@ -333,6 +542,299 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="KeysBy">KeysBy</span>
|
||||||
|
|
||||||
|
<p>创建一个切片,其元素是每个map的key调用mapper函数的结果。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func KeysBy[K comparable, V any, T any](m map[K]V, mapper func(item K) T) []T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "a",
|
||||||
|
3: "b",
|
||||||
|
}
|
||||||
|
|
||||||
|
keys := maputil.KeysBy(m, func(n int) int {
|
||||||
|
return n + 1
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Ints(keys)
|
||||||
|
|
||||||
|
fmt.Println(keys)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ValuesBy">ValuesBy</span>
|
||||||
|
|
||||||
|
<p>创建一个切片,其元素是每个map的value调用mapper函数的结果。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ValuesBy[K comparable, V any, T any](m map[K]V, mapper func(item V) T) []T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "b",
|
||||||
|
3: "c",
|
||||||
|
}
|
||||||
|
values := maputil.ValuesBy(m, func(v string) string {
|
||||||
|
switch v {
|
||||||
|
case "a":
|
||||||
|
return "a-1"
|
||||||
|
case "b":
|
||||||
|
return "b-2"
|
||||||
|
case "c":
|
||||||
|
return "c-3"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Strings(values)
|
||||||
|
|
||||||
|
fmt.Println(values)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [a-1 b-2 c-3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="MapKeys">MapKeys</span>
|
||||||
|
|
||||||
|
<p>操作map的每个key,然后转为新的map。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func MapKeys[K comparable, V any, T comparable](m map[K]V, iteratee func(key K, value V) T) map[T]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "b",
|
||||||
|
3: "c",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.MapKeys(m, func(k int, _ string) string {
|
||||||
|
return strconv.Itoa(k)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[1:a 2:b 3:c]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="MapValues">MapValues</span>
|
||||||
|
|
||||||
|
<p>操作map的每个value,然后转为新的map。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func MapValues[K comparable, V any, T any](m map[K]V, iteratee func(key K, value V) T) map[K]T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "b",
|
||||||
|
3: "c",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.MapValues(m, func(k int, v string) string {
|
||||||
|
return v + strconv.Itoa(k)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[1:a1 2:b2 3:c3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="Entry">Entry</span>
|
||||||
|
|
||||||
|
<p>将map转换为键/值对切片。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Entry[K comparable, V any] struct {
|
||||||
|
Key K
|
||||||
|
Value V
|
||||||
|
}
|
||||||
|
func Entries[K comparable, V any](m map[K]V) []Entry[K, V]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := maputil.Entries(m)
|
||||||
|
|
||||||
|
sort.Slice(result, func(i, j int) bool {
|
||||||
|
return result[i].Value < result[j].Value
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [{a 1} {b 2} {c 3}]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="FromEntries">FromEntries</span>
|
||||||
|
|
||||||
|
<p>基于键/值对的切片创建map。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Entry[K comparable, V any] struct {
|
||||||
|
Key K
|
||||||
|
Value V
|
||||||
|
}
|
||||||
|
func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result := maputil.FromEntries([]Entry[string, int]{
|
||||||
|
{Key: "a", Value: 1},
|
||||||
|
{Key: "b", Value: 2},
|
||||||
|
{Key: "c", Value: 3},
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 b:2 c:3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Transform">Transform</span>
|
||||||
|
|
||||||
|
<p>将map转换为其他类型的map。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Transform[K1 comparable, V1 any, K2 comparable, V2 any](m map[K1]V1, iteratee func(key K1, value V1) (K2, V2)) map[K2]V2
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := Transform(m, func(k string, v int) (string, string) {
|
||||||
|
return k, strconv.Itoa(v)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 b:2 c:3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="IsDisjoint">IsDisjoint</span>
|
### <span id="IsDisjoint">IsDisjoint</span>
|
||||||
|
|
||||||
<p>验证两个map是否具有不同的key</p>
|
<p>验证两个map是否具有不同的key</p>
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ import (
|
|||||||
- [RoundToFloat](#RoundToFloat)
|
- [RoundToFloat](#RoundToFloat)
|
||||||
- [RoundToString](#RoundToString)
|
- [RoundToString](#RoundToString)
|
||||||
- [TruncRound](#TruncRound)
|
- [TruncRound](#TruncRound)
|
||||||
|
- [Range](#Range)
|
||||||
|
- [RangeWithStep](#RangeWithStep)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -476,3 +478,81 @@ func main() {
|
|||||||
// 0.125
|
// 0.125
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Range">Range</span>
|
||||||
|
|
||||||
|
<p>Creates a slice of numbers from start with specified count, element step is 1.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Range[T constraints.Integer | constraints.Float](start T, count int) []T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/mathutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := mathutil.Range(1, 4)
|
||||||
|
result2 := mathutil.Range(1, -4)
|
||||||
|
result3 := mathutil.Range(-4, 4)
|
||||||
|
result4 := mathutil.Range(1.0, 4)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [-4 -3 -2 -1]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RangeWithStep">RangeWithStep</span>
|
||||||
|
|
||||||
|
<p>Creates a slice of numbers from start to end with specified step.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RangeWithStep[T constraints.Integer | constraints.Float](start, end, step T) []T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/mathutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := mathutil.RangeWithStep(1, 4, 1)
|
||||||
|
result2 := mathutil.RangeWithStep(1, -1, 0)
|
||||||
|
result3 := mathutil.RangeWithStep(-4, 1, 2)
|
||||||
|
result4 := mathutil.RangeWithStep(1.0, 4.0, 1.1)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
// []
|
||||||
|
// [-4 -2 0]
|
||||||
|
// [1 2.1 3.2]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ import (
|
|||||||
- [RoundToFloat](#RoundToFloat)
|
- [RoundToFloat](#RoundToFloat)
|
||||||
- [RoundToString](#RoundToString)
|
- [RoundToString](#RoundToString)
|
||||||
- [TruncRound](#TruncRound)
|
- [TruncRound](#TruncRound)
|
||||||
|
- [Range](#Range)
|
||||||
|
- [RangeWithStep](#RangeWithStep)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -476,3 +478,81 @@ func main() {
|
|||||||
// 0.125
|
// 0.125
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Range">Range</span>
|
||||||
|
|
||||||
|
<p>根据指定的起始值和数量,创建一个数字切片。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Range[T constraints.Integer | constraints.Float](start T, count int) []T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/mathutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := mathutil.Range(1, 4)
|
||||||
|
result2 := mathutil.Range(1, -4)
|
||||||
|
result3 := mathutil.Range(-4, 4)
|
||||||
|
result4 := mathutil.Range(1.0, 4)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [-4 -3 -2 -1]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RangeWithStep">RangeWithStep</span>
|
||||||
|
|
||||||
|
<p>根据指定的起始值,结束值,步长,创建一个数字切片。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RangeWithStep[T constraints.Integer | constraints.Float](start, end, step T) []T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/mathutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := mathutil.RangeWithStep(1, 4, 1)
|
||||||
|
result2 := mathutil.RangeWithStep(1, -1, 0)
|
||||||
|
result3 := mathutil.RangeWithStep(-4, 1, 2)
|
||||||
|
result4 := mathutil.RangeWithStep(1.0, 4.0, 1.1)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
// []
|
||||||
|
// [-4 -2 0]
|
||||||
|
// [1 2.1 3.2]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -590,21 +590,29 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
type TodoQuery struct {
|
type TodoQuery struct {
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
Name string `json:"name"`
|
UserId int `json:"userId"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Status string
|
||||||
}
|
}
|
||||||
todoQuery := TodoQuery{
|
item := TodoQuery{
|
||||||
Id: 1,
|
Id: 1,
|
||||||
Name: "Test",
|
UserId: 123,
|
||||||
|
Name: "test",
|
||||||
|
Status: "completed",
|
||||||
}
|
}
|
||||||
todoValues := netutil.StructToUrlValues(todoQuery)
|
queryValues := netutil.StructToUrlValues(item)
|
||||||
|
|
||||||
fmt.Println(todoValues.Get("id"))
|
fmt.Println(todoValues.Get("id"))
|
||||||
|
fmt.Println(todoValues.Get("userId"))
|
||||||
fmt.Println(todoValues.Get("name"))
|
fmt.Println(todoValues.Get("name"))
|
||||||
|
fmt.Println(todoValues.Get("status"))
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 1
|
// 1
|
||||||
// Test
|
// 123
|
||||||
|
// test
|
||||||
|
//
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -592,21 +592,29 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
type TodoQuery struct {
|
type TodoQuery struct {
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
Name string `json:"name"`
|
UserId int `json:"userId"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Status string
|
||||||
}
|
}
|
||||||
todoQuery := TodoQuery{
|
item := TodoQuery{
|
||||||
Id: 1,
|
Id: 1,
|
||||||
Name: "Test",
|
UserId: 123,
|
||||||
|
Name: "test",
|
||||||
|
Status: "completed",
|
||||||
}
|
}
|
||||||
todoValues := netutil.StructToUrlValues(todoQuery)
|
queryValues := netutil.StructToUrlValues(item)
|
||||||
|
|
||||||
fmt.Println(todoValues.Get("id"))
|
fmt.Println(todoValues.Get("id"))
|
||||||
|
fmt.Println(todoValues.Get("userId"))
|
||||||
fmt.Println(todoValues.Get("name"))
|
fmt.Println(todoValues.Get("name"))
|
||||||
|
fmt.Println(todoValues.Get("status"))
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 1
|
// 1
|
||||||
// Test
|
// 123
|
||||||
|
// test
|
||||||
|
//
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
122
docs/slice.md
122
docs/slice.md
@@ -24,6 +24,7 @@ import (
|
|||||||
|
|
||||||
- [AppendIfAbsent](#AppendIfAbsent)
|
- [AppendIfAbsent](#AppendIfAbsent)
|
||||||
- [Contain](#Contain)
|
- [Contain](#Contain)
|
||||||
|
- [ContainBy](#ContainBy)
|
||||||
- [ContainSubSlice](#ContainSubSlice)
|
- [ContainSubSlice](#ContainSubSlice)
|
||||||
- [Chunk](#Chunk)
|
- [Chunk](#Chunk)
|
||||||
- [Compact](#Compact)
|
- [Compact](#Compact)
|
||||||
@@ -56,6 +57,8 @@ import (
|
|||||||
- [IndexOf](#IndexOf)
|
- [IndexOf](#IndexOf)
|
||||||
- [LastIndexOf](#LastIndexOf)
|
- [LastIndexOf](#LastIndexOf)
|
||||||
- [Map](#Map)
|
- [Map](#Map)
|
||||||
|
- [FilterMap](#FilterMap)
|
||||||
|
- [FlatMap](#FlatMap)
|
||||||
- [Merge](#Merge)
|
- [Merge](#Merge)
|
||||||
- [Reverse](#Reverse)
|
- [Reverse](#Reverse)
|
||||||
- [Reduce](#Reduce)
|
- [Reduce](#Reduce)
|
||||||
@@ -149,6 +152,51 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="ContainBy">ContainBy</span>
|
||||||
|
|
||||||
|
<p>returns true if predicate function return true.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ContainBy[T any](slice []T, predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type foo struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
}
|
||||||
|
|
||||||
|
array1 := []foo{{A: "1", B: 1}, {A: "2", B: 2}}
|
||||||
|
result1 := slice.ContainBy(array1, func(f foo) bool { return f.A == "1" && f.B == 1 })
|
||||||
|
result2 := slice.ContainBy(array1, func(f foo) bool { return f.A == "2" && f.B == 1 })
|
||||||
|
|
||||||
|
array2 := []string{"a", "b", "c"}
|
||||||
|
result3 := slice.ContainBy(array2, func(t string) bool { return t == "a" })
|
||||||
|
result4 := slice.ContainBy(array2, func(t string) bool { return t == "d" })
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="ContainSubSlice">ContainSubSlice</span>
|
### <span id="ContainSubSlice">ContainSubSlice</span>
|
||||||
|
|
||||||
<p>Check if the slice contain subslice or not.</p>
|
<p>Check if the slice contain subslice or not.</p>
|
||||||
@@ -1252,6 +1300,76 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="FilterMap">FilterMap</span>
|
||||||
|
|
||||||
|
<p>Returns a slice which apply both filtering and mapping to the given slice. iteratee callback function should returntwo values: 1, mapping result. 2, whether the result element should be included or not.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FilterMap[T any, U any](slice []T, iteratee func(index int, item T) (U, bool)) []U
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
nums := []int{1, 2, 3, 4, 5}
|
||||||
|
|
||||||
|
getEvenNumStr := func(i, num int) (string, bool) {
|
||||||
|
if num%2 == 0 {
|
||||||
|
return strconv.FormatInt(int64(num), 10), true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
result := slice.FilterMap(nums, getEvenNumStr)
|
||||||
|
|
||||||
|
fmt.Printf("%#v", result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []string{"2", "4"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FlatMap">FlatMap</span>
|
||||||
|
|
||||||
|
<p>Manipulates a slice and transforms and flattens it to a slice of another type.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FlatMap[T any, U any](slice []T, iteratee func(index int, item T) []U) []U
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
nums := []int{1, 2, 3, 4}
|
||||||
|
|
||||||
|
result := slice.FlatMap(nums, func(i int, num int) []string {
|
||||||
|
s := "hi-" + strconv.FormatInt(int64(num), 10)
|
||||||
|
return []string{s}
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Printf("%#v", result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []string{"hi-1", "hi-2", "hi-3", "hi-4"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="Merge">Merge</span>
|
### <span id="Merge">Merge</span>
|
||||||
|
|
||||||
<p>Merge all given slices into one slice.</p>
|
<p>Merge all given slices into one slice.</p>
|
||||||
@@ -1467,8 +1585,8 @@ func main() {
|
|||||||
nums := []int{1, 2, 3, 4, 5}
|
nums := []int{1, 2, 3, 4, 5}
|
||||||
result := slice.Shuffle(nums)
|
result := slice.Shuffle(nums)
|
||||||
|
|
||||||
fmt.Println(res)
|
fmt.Println(res)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// [3 1 5 4 2] (random order)
|
// [3 1 5 4 2] (random order)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
|
|
||||||
- [AppendIfAbsent](#AppendIfAbsent)
|
- [AppendIfAbsent](#AppendIfAbsent)
|
||||||
- [Contain](#Contain)
|
- [Contain](#Contain)
|
||||||
|
- [ContainBy](#ContainBy)
|
||||||
- [ContainSubSlice](#ContainSubSlice)
|
- [ContainSubSlice](#ContainSubSlice)
|
||||||
- [Chunk](#Chunk)
|
- [Chunk](#Chunk)
|
||||||
- [Compact](#Compact)
|
- [Compact](#Compact)
|
||||||
@@ -56,6 +57,8 @@ import (
|
|||||||
- [IndexOf](#IndexOf)
|
- [IndexOf](#IndexOf)
|
||||||
- [LastIndexOf](#LastIndexOf)
|
- [LastIndexOf](#LastIndexOf)
|
||||||
- [Map](#Map)
|
- [Map](#Map)
|
||||||
|
- [FilterMap](#FilterMap)
|
||||||
|
- [FlatMap](#FlatMap)
|
||||||
- [Merge](#Merge)
|
- [Merge](#Merge)
|
||||||
- [Reverse](#Reverse)
|
- [Reverse](#Reverse)
|
||||||
- [Reduce](#Reduce)
|
- [Reduce](#Reduce)
|
||||||
@@ -149,6 +152,51 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="ContainBy">ContainBy</span>
|
||||||
|
|
||||||
|
<p>根据predicate函数判断切片是否包含某个值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ContainBy[T any](slice []T, predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type foo struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
}
|
||||||
|
|
||||||
|
array1 := []foo{{A: "1", B: 1}, {A: "2", B: 2}}
|
||||||
|
result1 := slice.ContainBy(array1, func(f foo) bool { return f.A == "1" && f.B == 1 })
|
||||||
|
result2 := slice.ContainBy(array1, func(f foo) bool { return f.A == "2" && f.B == 1 })
|
||||||
|
|
||||||
|
array2 := []string{"a", "b", "c"}
|
||||||
|
result3 := slice.ContainBy(array2, func(t string) bool { return t == "a" })
|
||||||
|
result4 := slice.ContainBy(array2, func(t string) bool { return t == "d" })
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="ContainSubSlice">ContainSubSlice</span>
|
### <span id="ContainSubSlice">ContainSubSlice</span>
|
||||||
|
|
||||||
<p>判断slice是否包含subslice</p>
|
<p>判断slice是否包含subslice</p>
|
||||||
@@ -1254,6 +1302,76 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="FilterMap">FilterMap</span>
|
||||||
|
|
||||||
|
<p>返回一个将filter和map操作应用于给定切片的切片。 iteratee回调函数应该返回两个值:1,结果值。2,结果值是否应该被包含在返回的切片中。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FilterMap[T any, U any](slice []T, iteratee func(index int, item T) (U, bool)) []U
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
nums := []int{1, 2, 3, 4, 5}
|
||||||
|
|
||||||
|
getEvenNumStr := func(i, num int) (string, bool) {
|
||||||
|
if num%2 == 0 {
|
||||||
|
return strconv.FormatInt(int64(num), 10), true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
result := slice.FilterMap(nums, getEvenNumStr)
|
||||||
|
|
||||||
|
fmt.Printf("%#v", result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []string{"2", "4"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FlatMap">FlatMap</span>
|
||||||
|
|
||||||
|
<p>将切片转换为其它类型切片。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FlatMap[T any, U any](slice []T, iteratee func(index int, item T) []U) []U
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
nums := []int{1, 2, 3, 4}
|
||||||
|
|
||||||
|
result := slice.FlatMap(nums, func(i int, num int) []string {
|
||||||
|
s := "hi-" + strconv.FormatInt(int64(num), 10)
|
||||||
|
return []string{s}
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Printf("%#v", result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []string{"hi-1", "hi-2", "hi-3", "hi-4"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="Merge">Merge</span>
|
### <span id="Merge">Merge</span>
|
||||||
|
|
||||||
<p>合并多个切片(不会消除重复元素).</p>
|
<p>合并多个切片(不会消除重复元素).</p>
|
||||||
|
|||||||
138
docs/strutil.md
138
docs/strutil.md
@@ -33,8 +33,9 @@ import (
|
|||||||
- [UpperKebabCase](#UpperKebabCase)
|
- [UpperKebabCase](#UpperKebabCase)
|
||||||
- [LowerFirst](#LowerFirst)
|
- [LowerFirst](#LowerFirst)
|
||||||
- [UpperFirst](#UpperFirst)
|
- [UpperFirst](#UpperFirst)
|
||||||
- [PadEnd](#PadEnd)
|
- [Pad](#Pad)
|
||||||
- [PadStart](#PadStart)
|
- [PadStart](#PadStart)
|
||||||
|
- [PadEnd](#PadEnd)
|
||||||
- [Reverse](#Reverse)
|
- [Reverse](#Reverse)
|
||||||
- [SnakeCase](#SnakeCase)
|
- [SnakeCase](#SnakeCase)
|
||||||
- [UpperSnakeCase](#UpperSnakeCase)
|
- [UpperSnakeCase](#UpperSnakeCase)
|
||||||
@@ -42,6 +43,8 @@ import (
|
|||||||
- [Substring](#Substring)
|
- [Substring](#Substring)
|
||||||
- [Wrap](#Wrap)
|
- [Wrap](#Wrap)
|
||||||
- [Unwrap](#Unwrap)
|
- [Unwrap](#Unwrap)
|
||||||
|
- [SplitWords](#SplitWords)
|
||||||
|
- [WordCount](#WordCount)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -449,6 +452,51 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Pad">Pad</span>
|
||||||
|
|
||||||
|
<p>Pads string on the left and right side if it's shorter than size.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Pad(source string, size int, padStr string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := strutil.Pad("foo", 1, "bar")
|
||||||
|
result2 := strutil.Pad("foo", 2, "bar")
|
||||||
|
result3 := strutil.Pad("foo", 3, "bar")
|
||||||
|
result4 := strutil.Pad("foo", 4, "bar")
|
||||||
|
result5 := strutil.Pad("foo", 5, "bar")
|
||||||
|
result6 := strutil.Pad("foo", 6, "bar")
|
||||||
|
result7 := strutil.Pad("foo", 7, "bar")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
fmt.Println(result7)
|
||||||
|
// Output:
|
||||||
|
// foo
|
||||||
|
// foo
|
||||||
|
// foo
|
||||||
|
// foob
|
||||||
|
// bfoob
|
||||||
|
// bfooba
|
||||||
|
// bafooba
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="PadEnd">PadEnd</span>
|
### <span id="PadEnd">PadEnd</span>
|
||||||
|
|
||||||
<p>Pads string on the right side if it's shorter than size.</p>
|
<p>Pads string on the right side if it's shorter than size.</p>
|
||||||
@@ -802,3 +850,91 @@ func main() {
|
|||||||
// *foo*
|
// *foo*
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="SplitWords">SplitWords</span>
|
||||||
|
|
||||||
|
<p>Splits a string into words, word only contains alphabetic characters.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func SplitWords(s string) []string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := strutil.SplitWords("a word")
|
||||||
|
result2 := strutil.SplitWords("I'am a programmer")
|
||||||
|
result3 := strutil.SplitWords("Bonjour, je suis programmeur")
|
||||||
|
result4 := strutil.SplitWords("a -b-c' 'd'e")
|
||||||
|
result5 := strutil.SplitWords("你好,我是一名码农")
|
||||||
|
result6 := strutil.SplitWords("こんにちは,私はプログラマーです")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [a word]
|
||||||
|
// [I'am a programmer]
|
||||||
|
// [Bonjour je suis programmeur]
|
||||||
|
// [a b-c' d'e]
|
||||||
|
// []
|
||||||
|
// []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="WordCount">WordCount</span>
|
||||||
|
|
||||||
|
<p>Return the number of meaningful word, word only contains alphabetic characters.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func WordCount(s string) int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := strutil.WordCount("a word")
|
||||||
|
result2 := strutil.WordCount("I'am a programmer")
|
||||||
|
result3 := strutil.WordCount("Bonjour, je suis programmeur")
|
||||||
|
result4 := strutil.WordCount("a -b-c' 'd'e")
|
||||||
|
result5 := strutil.WordCount("你好,我是一名码农")
|
||||||
|
result6 := strutil.WordCount("こんにちは,私はプログラマーです")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 2
|
||||||
|
// 3
|
||||||
|
// 4
|
||||||
|
// 3
|
||||||
|
// 0
|
||||||
|
// 0
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -33,6 +33,7 @@ import (
|
|||||||
- [UpperKebabCase](#UpperKebabCase)
|
- [UpperKebabCase](#UpperKebabCase)
|
||||||
- [LowerFirst](#LowerFirst)
|
- [LowerFirst](#LowerFirst)
|
||||||
- [UpperFirst](#UpperFirst)
|
- [UpperFirst](#UpperFirst)
|
||||||
|
- [Pad](#Pad)
|
||||||
- [PadEnd](#PadEnd)
|
- [PadEnd](#PadEnd)
|
||||||
- [PadStart](#PadStart)
|
- [PadStart](#PadStart)
|
||||||
- [Reverse](#Reverse)
|
- [Reverse](#Reverse)
|
||||||
@@ -42,6 +43,8 @@ import (
|
|||||||
- [Substring](#Substring)
|
- [Substring](#Substring)
|
||||||
- [Wrap](#Wrap)
|
- [Wrap](#Wrap)
|
||||||
- [Unwrap](#Unwrap)
|
- [Unwrap](#Unwrap)
|
||||||
|
- [SplitWords](#SplitWords)
|
||||||
|
- [WordCount](#WordCount)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -449,6 +452,51 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Pad">Pad</span>
|
||||||
|
|
||||||
|
<p>如果字符串长度短于size,则在左右两侧填充字符串。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Pad(source string, size int, padStr string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := strutil.Pad("foo", 1, "bar")
|
||||||
|
result2 := strutil.Pad("foo", 2, "bar")
|
||||||
|
result3 := strutil.Pad("foo", 3, "bar")
|
||||||
|
result4 := strutil.Pad("foo", 4, "bar")
|
||||||
|
result5 := strutil.Pad("foo", 5, "bar")
|
||||||
|
result6 := strutil.Pad("foo", 6, "bar")
|
||||||
|
result7 := strutil.Pad("foo", 7, "bar")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
fmt.Println(result7)
|
||||||
|
// Output:
|
||||||
|
// foo
|
||||||
|
// foo
|
||||||
|
// foo
|
||||||
|
// foob
|
||||||
|
// bfoob
|
||||||
|
// bfooba
|
||||||
|
// bafooba
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="PadEnd">PadEnd</span>
|
### <span id="PadEnd">PadEnd</span>
|
||||||
|
|
||||||
<p>如果字符串长度短于size,则在右侧填充字符串。</p>
|
<p>如果字符串长度短于size,则在右侧填充字符串。</p>
|
||||||
@@ -802,3 +850,90 @@ func main() {
|
|||||||
// *foo*
|
// *foo*
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="SplitWords">SplitWords</span>
|
||||||
|
|
||||||
|
<p>将字符串拆分为单词,只支持字母字符单词。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func SplitWords(s string) []string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := strutil.SplitWords("a word")
|
||||||
|
result2 := strutil.SplitWords("I'am a programmer")
|
||||||
|
result3 := strutil.SplitWords("Bonjour, je suis programmeur")
|
||||||
|
result4 := strutil.SplitWords("a -b-c' 'd'e")
|
||||||
|
result5 := strutil.SplitWords("你好,我是一名码农")
|
||||||
|
result6 := strutil.SplitWords("こんにちは,私はプログラマーです")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [a word]
|
||||||
|
// [I'am a programmer]
|
||||||
|
// [Bonjour je suis programmeur]
|
||||||
|
// [a b-c' d'e]
|
||||||
|
// []
|
||||||
|
// []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="WordCount">WordCount</span>
|
||||||
|
|
||||||
|
<p>返回有意义单词的数量,只支持字母字符单词。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func WordCount(s string) int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := strutil.WordCount("a word")
|
||||||
|
result2 := strutil.WordCount("I'am a programmer")
|
||||||
|
result3 := strutil.WordCount("Bonjour, je suis programmeur")
|
||||||
|
result4 := strutil.WordCount("a -b-c' 'd'e")
|
||||||
|
result5 := strutil.WordCount("你好,我是一名码农")
|
||||||
|
result6 := strutil.WordCount("こんにちは,私はプログラマーです")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 2
|
||||||
|
// 3
|
||||||
|
// 4
|
||||||
|
// 3
|
||||||
|
// 0
|
||||||
|
// 0
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -133,7 +133,7 @@ func main() {
|
|||||||
err1 := xerror.New("error").With("level", "high")
|
err1 := xerror.New("error").With("level", "high")
|
||||||
wrapErr := errors.Wrap(err1, "oops")
|
wrapErr := errors.Wrap(err1, "oops")
|
||||||
|
|
||||||
err := xerror.Unwrap(err1)
|
err := xerror.Unwrap(wrapErr)
|
||||||
|
|
||||||
values := err.Values()
|
values := err.Values()
|
||||||
fmt.Println(values["level"])
|
fmt.Println(values["level"])
|
||||||
@@ -441,7 +441,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
err := New("error")
|
err := xerror.New("error")
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ func main() {
|
|||||||
err1 := xerror.New("error").With("level", "high")
|
err1 := xerror.New("error").With("level", "high")
|
||||||
wrapErr := errors.Wrap(err1, "oops")
|
wrapErr := errors.Wrap(err1, "oops")
|
||||||
|
|
||||||
err := xerror.Unwrap(err1)
|
err := xerror.Unwrap(wrapErr)
|
||||||
|
|
||||||
values := err.Values()
|
values := err.Values()
|
||||||
fmt.Println(values["level"])
|
fmt.Println(values["level"])
|
||||||
@@ -441,7 +441,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
err := New("error")
|
err := xerror.New("error")
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
|
|||||||
165
maputil/map.go
165
maputil/map.go
@@ -4,7 +4,11 @@
|
|||||||
// Package maputil includes some functions to manipulate map.
|
// Package maputil includes some functions to manipulate map.
|
||||||
package maputil
|
package maputil
|
||||||
|
|
||||||
import "reflect"
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
// Keys returns a slice of the map's keys.
|
// Keys returns a slice of the map's keys.
|
||||||
// Play: https://go.dev/play/p/xNB5bTb97Wd
|
// Play: https://go.dev/play/p/xNB5bTb97Wd
|
||||||
@@ -34,6 +38,30 @@ func Values[K comparable, V any](m map[K]V) []V {
|
|||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KeysBy creates a slice whose element is the result of function mapper invoked by every map's key.
|
||||||
|
// Play: https://go.dev/play/p/hI371iB8Up8
|
||||||
|
func KeysBy[K comparable, V any, T any](m map[K]V, mapper func(item K) T) []T {
|
||||||
|
keys := make([]T, 0, len(m))
|
||||||
|
|
||||||
|
for k := range m {
|
||||||
|
keys = append(keys, mapper(k))
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValuesBy creates a slice whose element is the result of function mapper invoked by every map's value.
|
||||||
|
// Play: https://go.dev/play/p/sg9-oRidh8f
|
||||||
|
func ValuesBy[K comparable, V any, T any](m map[K]V, mapper func(item V) T) []T {
|
||||||
|
keys := make([]T, 0, len(m))
|
||||||
|
|
||||||
|
for _, v := range m {
|
||||||
|
keys = append(keys, mapper(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
// Merge maps, next key will overwrite previous key.
|
// Merge maps, next key will overwrite previous key.
|
||||||
// Play: https://go.dev/play/p/H95LENF1uB-
|
// Play: https://go.dev/play/p/H95LENF1uB-
|
||||||
func Merge[K comparable, V any](maps ...map[K]V) map[K]V {
|
func Merge[K comparable, V any](maps ...map[K]V) map[K]V {
|
||||||
@@ -69,6 +97,71 @@ func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool)
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilterByKeys iterates over map, return a new map whose keys are all given keys.
|
||||||
|
// Play: https://go.dev/play/p/7ov6BJHbVqh
|
||||||
|
func FilterByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V {
|
||||||
|
result := make(map[K]V)
|
||||||
|
|
||||||
|
for k, v := range m {
|
||||||
|
if slice.Contain(keys, k) {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByValues iterates over map, return a new map whose values are all given values.
|
||||||
|
// Play: https://go.dev/play/p/P3-9MdcXegR
|
||||||
|
func FilterByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V {
|
||||||
|
result := make(map[K]V)
|
||||||
|
|
||||||
|
for k, v := range m {
|
||||||
|
if slice.Contain(values, v) {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// OmitBy is the opposite of Filter, removes all the map elements for which the predicate function returns true.
|
||||||
|
// Play: https://go.dev/play/p/YJM4Hj5hNwm
|
||||||
|
func OmitBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V {
|
||||||
|
result := make(map[K]V)
|
||||||
|
|
||||||
|
for k, v := range m {
|
||||||
|
if !predicate(k, v) {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// OmitByKeys the opposite of FilterByKeys, extracts all the map elements which keys are not omitted.
|
||||||
|
// Play: https://go.dev/play/p/jXGrWDBfSRp
|
||||||
|
func OmitByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V {
|
||||||
|
result := make(map[K]V)
|
||||||
|
|
||||||
|
for k, v := range m {
|
||||||
|
if !slice.Contain(keys, k) {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// OmitByValues the opposite of FilterByValues. remov all elements whose value are in the give slice.
|
||||||
|
// Play: https://go.dev/play/p/XB7Y10uw20_U
|
||||||
|
func OmitByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V {
|
||||||
|
result := make(map[K]V)
|
||||||
|
|
||||||
|
for k, v := range m {
|
||||||
|
if !slice.Contain(values, v) {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// Intersect iterates over maps, return a new map of key and value pairs in all given maps.
|
// Intersect iterates over maps, return a new map of key and value pairs in all given maps.
|
||||||
// Play: https://go.dev/play/p/Zld0oj3sjcC
|
// Play: https://go.dev/play/p/Zld0oj3sjcC
|
||||||
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
|
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
|
||||||
@@ -126,3 +219,73 @@ func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Entry is a key/value pairs.
|
||||||
|
type Entry[K comparable, V any] struct {
|
||||||
|
Key K
|
||||||
|
Value V
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entries transforms a map into array of key/value pairs.
|
||||||
|
// Play: https://go.dev/play/p/Ltb11LNcElY
|
||||||
|
func Entries[K comparable, V any](m map[K]V) []Entry[K, V] {
|
||||||
|
entries := make([]Entry[K, V], 0, len(m))
|
||||||
|
|
||||||
|
for k, v := range m {
|
||||||
|
entries = append(entries, Entry[K, V]{
|
||||||
|
Key: k,
|
||||||
|
Value: v,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromEntries creates a map based on a slice of key/value pairs
|
||||||
|
// Play: https://go.dev/play/p/fTdu4sCNjQO
|
||||||
|
func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V {
|
||||||
|
result := make(map[K]V, len(entries))
|
||||||
|
|
||||||
|
for _, v := range entries {
|
||||||
|
result[v.Key] = v.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform a map to another type map.
|
||||||
|
// Play: https://go.dev/play/p/P6ovfToM3zj
|
||||||
|
func Transform[K1 comparable, V1 any, K2 comparable, V2 any](m map[K1]V1, iteratee func(key K1, value V1) (K2, V2)) map[K2]V2 {
|
||||||
|
result := make(map[K2]V2, len(m))
|
||||||
|
|
||||||
|
for k1, v1 := range m {
|
||||||
|
k2, v2 := iteratee(k1, v1)
|
||||||
|
result[k2] = v2
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapKeys transforms a map to other type map by manipulating it's keys.
|
||||||
|
// Play: https://go.dev/play/p/8scDxWeBDKd
|
||||||
|
func MapKeys[K comparable, V any, T comparable](m map[K]V, iteratee func(key K, value V) T) map[T]V {
|
||||||
|
result := make(map[T]V, len(m))
|
||||||
|
|
||||||
|
for k, v := range m {
|
||||||
|
result[iteratee(k, v)] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapValues transforms a map to other type map by manipulating it's values.
|
||||||
|
// Play: https://go.dev/play/p/g92aY3fc7Iw
|
||||||
|
func MapValues[K comparable, V any, T any](m map[K]V, iteratee func(key K, value V) T) map[K]T {
|
||||||
|
result := make(map[K]T, len(m))
|
||||||
|
|
||||||
|
for k, v := range m {
|
||||||
|
result[k] = iteratee(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package maputil
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleKeys() {
|
func ExampleKeys() {
|
||||||
@@ -41,6 +42,51 @@ func ExampleValues() {
|
|||||||
// [a a b c d]
|
// [a a b c d]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleKeysBy() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "a",
|
||||||
|
3: "b",
|
||||||
|
}
|
||||||
|
|
||||||
|
keys := KeysBy(m, func(n int) int {
|
||||||
|
return n + 1
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Ints(keys)
|
||||||
|
|
||||||
|
fmt.Println(keys)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 3 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleValuesBy() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "b",
|
||||||
|
3: "c",
|
||||||
|
}
|
||||||
|
values := ValuesBy(m, func(v string) string {
|
||||||
|
switch v {
|
||||||
|
case "a":
|
||||||
|
return "a-1"
|
||||||
|
case "b":
|
||||||
|
return "b-2"
|
||||||
|
case "c":
|
||||||
|
return "c-3"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Strings(values)
|
||||||
|
|
||||||
|
fmt.Println(values)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [a-1 b-2 c-3]
|
||||||
|
}
|
||||||
func ExampleMerge() {
|
func ExampleMerge() {
|
||||||
m1 := map[int]string{
|
m1 := map[int]string{
|
||||||
1: "a",
|
1: "a",
|
||||||
@@ -99,6 +145,40 @@ func ExampleFilter() {
|
|||||||
// map[b:2 d:4]
|
// map[b:2 d:4]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleFilterByKeys() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := FilterByKeys(m, []string{"a", "b"})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 b:2]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleFilterByValues() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := FilterByValues(m, []int{3, 4})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[c:3 d:4]
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleIntersect() {
|
func ExampleIntersect() {
|
||||||
m1 := map[string]int{
|
m1 := map[string]int{
|
||||||
"a": 1,
|
"a": 1,
|
||||||
@@ -179,3 +259,141 @@ func ExampleIsDisjoint() {
|
|||||||
// true
|
// true
|
||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleEntries() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := Entries(m)
|
||||||
|
|
||||||
|
sort.Slice(result, func(i, j int) bool {
|
||||||
|
return result[i].Value < result[j].Value
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [{a 1} {b 2} {c 3}]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleFromEntries() {
|
||||||
|
|
||||||
|
result := FromEntries([]Entry[string, int]{
|
||||||
|
{Key: "a", Value: 1},
|
||||||
|
{Key: "b", Value: 2},
|
||||||
|
{Key: "c", Value: 3},
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 b:2 c:3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleTransform() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := Transform(m, func(k string, v int) (string, string) {
|
||||||
|
return k, strconv.Itoa(v)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 b:2 c:3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleMapKeys() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "b",
|
||||||
|
3: "c",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := MapKeys(m, func(k int, _ string) string {
|
||||||
|
return strconv.Itoa(k)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[1:a 2:b 3:c]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleMapValues() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "b",
|
||||||
|
3: "c",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := MapValues(m, func(k int, v string) string {
|
||||||
|
return v + strconv.Itoa(k)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[1:a1 2:b2 3:c3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleOmitBy() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
isEven := func(_ string, value int) bool {
|
||||||
|
return value%2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
result := OmitBy(m, isEven)
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 c:3 e:5]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleOmitByKeys() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := OmitByKeys(m, []string{"a", "b"})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[c:3 d:4 e:5]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleOmitByValues() {
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := OmitByValues(m, []int{4, 5})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// map[a:1 b:2 c:3]
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package maputil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/v2/internal"
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
@@ -41,6 +42,51 @@ func TestValues(t *testing.T) {
|
|||||||
assert.Equal([]string{"a", "a", "b", "c", "d"}, values)
|
assert.Equal([]string{"a", "a", "b", "c", "d"}, values)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestKeysBy(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestKeysBy")
|
||||||
|
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "a",
|
||||||
|
3: "b",
|
||||||
|
}
|
||||||
|
|
||||||
|
keys := KeysBy(m, func(n int) int {
|
||||||
|
return n + 1
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Ints(keys)
|
||||||
|
|
||||||
|
assert.Equal([]int{2, 3, 4}, keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValuesBy(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestValuesBy")
|
||||||
|
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "b",
|
||||||
|
3: "c",
|
||||||
|
}
|
||||||
|
|
||||||
|
values := ValuesBy(m, func(v string) string {
|
||||||
|
switch v {
|
||||||
|
case "a":
|
||||||
|
return "a-1"
|
||||||
|
case "b":
|
||||||
|
return "b-2"
|
||||||
|
case "c":
|
||||||
|
return "c-3"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Strings(values)
|
||||||
|
|
||||||
|
assert.Equal([]string{"a-1", "b-2", "c-3"}, values)
|
||||||
|
}
|
||||||
|
|
||||||
func TestMerge(t *testing.T) {
|
func TestMerge(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestMerge")
|
assert := internal.NewAssert(t, "TestMerge")
|
||||||
|
|
||||||
@@ -104,6 +150,107 @@ func TestFilter(t *testing.T) {
|
|||||||
}, acturl)
|
}, acturl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFilterByKeys(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestFilterByKeys")
|
||||||
|
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
acturl := FilterByKeys(m, []string{"a", "b"})
|
||||||
|
|
||||||
|
assert.Equal(map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
}, acturl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByValues(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestFilterByValues")
|
||||||
|
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
acturl := FilterByValues(m, []int{3, 4})
|
||||||
|
|
||||||
|
assert.Equal(map[string]int{
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
}, acturl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOmitBy(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestOmitBy")
|
||||||
|
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
isEven := func(_ string, value int) bool {
|
||||||
|
return value%2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
acturl := OmitBy(m, isEven)
|
||||||
|
|
||||||
|
assert.Equal(map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"c": 3,
|
||||||
|
"e": 5,
|
||||||
|
}, acturl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOmitByKeys(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestOmitByKeys")
|
||||||
|
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
acturl := OmitByKeys(m, []string{"a", "b"})
|
||||||
|
|
||||||
|
assert.Equal(map[string]int{
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}, acturl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOmitByValues(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestOmitByValues")
|
||||||
|
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
"e": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
acturl := OmitByValues(m, []int{4, 5})
|
||||||
|
|
||||||
|
assert.Equal(map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
}, acturl)
|
||||||
|
}
|
||||||
|
|
||||||
func TestIntersect(t *testing.T) {
|
func TestIntersect(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestIntersect")
|
assert := internal.NewAssert(t, "TestIntersect")
|
||||||
|
|
||||||
@@ -170,3 +317,104 @@ func TestIsDisjoint(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(false, IsDisjoint(m1, m3))
|
assert.Equal(false, IsDisjoint(m1, m3))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEntries(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestEntries")
|
||||||
|
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := Entries(m)
|
||||||
|
|
||||||
|
sort.Slice(result, func(i, j int) bool {
|
||||||
|
return result[i].Value < result[j].Value
|
||||||
|
})
|
||||||
|
|
||||||
|
expected := []Entry[string, int]{{Key: "a", Value: 1}, {Key: "b", Value: 2}, {Key: "c", Value: 3}}
|
||||||
|
|
||||||
|
assert.Equal(expected, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFromEntries(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestFromEntries")
|
||||||
|
|
||||||
|
result := FromEntries([]Entry[string, int]{
|
||||||
|
{Key: "a", Value: 1},
|
||||||
|
{Key: "b", Value: 2},
|
||||||
|
{Key: "c", Value: 3},
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(3, len(result))
|
||||||
|
assert.Equal(1, result["a"])
|
||||||
|
assert.Equal(2, result["b"])
|
||||||
|
assert.Equal(3, result["c"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTransform(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestTransform")
|
||||||
|
|
||||||
|
m := map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
result := Transform(m, func(k string, v int) (string, string) {
|
||||||
|
return k, strconv.Itoa(v)
|
||||||
|
})
|
||||||
|
|
||||||
|
expected := map[string]string{
|
||||||
|
"a": "1",
|
||||||
|
"b": "2",
|
||||||
|
"c": "3",
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(expected, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapKeys(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestMapKeys")
|
||||||
|
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "b",
|
||||||
|
3: "c",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := MapKeys(m, func(k int, _ string) string {
|
||||||
|
return strconv.Itoa(k)
|
||||||
|
})
|
||||||
|
|
||||||
|
expected := map[string]string{
|
||||||
|
"1": "a",
|
||||||
|
"2": "b",
|
||||||
|
"3": "c",
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(expected, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapValues(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestMapKeys")
|
||||||
|
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
2: "b",
|
||||||
|
3: "c",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := MapValues(m, func(k int, v string) string {
|
||||||
|
return v + strconv.Itoa(k)
|
||||||
|
})
|
||||||
|
|
||||||
|
expected := map[int]string{
|
||||||
|
1: "a1",
|
||||||
|
2: "b2",
|
||||||
|
3: "c3",
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(expected, result)
|
||||||
|
}
|
||||||
|
|||||||
@@ -183,3 +183,36 @@ func Average[T constraints.Integer | constraints.Float](numbers ...T) T {
|
|||||||
}
|
}
|
||||||
return sum / n
|
return sum / n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Range creates a slice of numbers from start with specified count, element step is 1.
|
||||||
|
// Play: todo
|
||||||
|
func Range[T constraints.Integer | constraints.Float](start T, count int) []T {
|
||||||
|
size := count
|
||||||
|
if count < 0 {
|
||||||
|
size = -count
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]T, size)
|
||||||
|
|
||||||
|
for i, j := 0, start; i < size; i, j = i+1, j+1 {
|
||||||
|
result[i] = j
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// RangeWithStep creates a slice of numbers from start to end with specified step.
|
||||||
|
// Play: todo
|
||||||
|
func RangeWithStep[T constraints.Integer | constraints.Float](start, end, step T) []T {
|
||||||
|
result := []T{}
|
||||||
|
|
||||||
|
if start >= end || step == 0 {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := start; i < end; i += step {
|
||||||
|
result = append(result, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -185,3 +185,39 @@ func ExampleMinBy() {
|
|||||||
// ab
|
// ab
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleRange() {
|
||||||
|
result1 := Range(1, 4)
|
||||||
|
result2 := Range(1, -4)
|
||||||
|
result3 := Range(-4, 4)
|
||||||
|
result4 := Range(1.0, 4)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [-4 -3 -2 -1]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleRangeWithStep() {
|
||||||
|
result1 := RangeWithStep(1, 4, 1)
|
||||||
|
result2 := RangeWithStep(1, -1, 0)
|
||||||
|
result3 := RangeWithStep(-4, 1, 2)
|
||||||
|
result4 := RangeWithStep(1.0, 4.0, 1.1)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
// []
|
||||||
|
// [-4 -2 0]
|
||||||
|
// [1 2.1 3.2]
|
||||||
|
}
|
||||||
|
|||||||
@@ -137,3 +137,33 @@ func TestMinBy(t *testing.T) {
|
|||||||
})
|
})
|
||||||
assert.Equal("", res3)
|
assert.Equal("", res3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRange(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "Range")
|
||||||
|
|
||||||
|
result1 := Range(1, 4)
|
||||||
|
result2 := Range(1, -4)
|
||||||
|
result3 := Range(-4, 4)
|
||||||
|
result4 := Range(1.0, 4)
|
||||||
|
result5 := Range(1, 0)
|
||||||
|
|
||||||
|
assert.Equal([]int{1, 2, 3, 4}, result1)
|
||||||
|
assert.Equal([]int{1, 2, 3, 4}, result2)
|
||||||
|
assert.Equal([]int{-4, -3, -2, -1}, result3)
|
||||||
|
assert.Equal([]float64{1.0, 2.0, 3.0, 4.0}, result4)
|
||||||
|
assert.Equal([]int{}, result5)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRangeWithStep(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "Range")
|
||||||
|
|
||||||
|
result1 := RangeWithStep(1, 4, 1)
|
||||||
|
result2 := RangeWithStep(1, -1, 0)
|
||||||
|
result3 := RangeWithStep(-4, 1, 2)
|
||||||
|
result4 := RangeWithStep(1.0, 4.0, 1.1)
|
||||||
|
|
||||||
|
assert.Equal([]int{1, 2, 3}, result1)
|
||||||
|
assert.Equal([]int{}, result2)
|
||||||
|
assert.Equal([]int{-4, -2, 0}, result3)
|
||||||
|
assert.Equal([]float64{1.0, 2.1, 3.2}, result4)
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,12 +21,11 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
|
||||||
"regexp"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
"github.com/duke-git/lancet/v2/slice"
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -219,7 +218,7 @@ func (client *HttpClient) setTLS(rawUrl string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setHeader set http rquest header
|
// setHeader set http request header
|
||||||
func (client *HttpClient) setHeader(req *http.Request, headers http.Header) {
|
func (client *HttpClient) setHeader(req *http.Request, headers http.Header) {
|
||||||
if headers == nil {
|
if headers == nil {
|
||||||
headers = make(http.Header)
|
headers = make(http.Header)
|
||||||
@@ -278,29 +277,15 @@ func validateRequest(req *HttpRequest) error {
|
|||||||
// StructToUrlValues convert struct to url valuse,
|
// StructToUrlValues convert struct to url valuse,
|
||||||
// only convert the field which is exported and has `json` tag.
|
// only convert the field which is exported and has `json` tag.
|
||||||
// Play: https://go.dev/play/p/pFqMkM40w9z
|
// Play: https://go.dev/play/p/pFqMkM40w9z
|
||||||
func StructToUrlValues(targetStruct any) url.Values {
|
func StructToUrlValues(targetStruct any) (url.Values, error) {
|
||||||
rv := reflect.ValueOf(targetStruct)
|
|
||||||
rt := reflect.TypeOf(targetStruct)
|
|
||||||
|
|
||||||
if rt.Kind() == reflect.Ptr {
|
|
||||||
rt = rt.Elem()
|
|
||||||
}
|
|
||||||
if rt.Kind() != reflect.Struct {
|
|
||||||
panic(fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", targetStruct))
|
|
||||||
}
|
|
||||||
|
|
||||||
result := url.Values{}
|
result := url.Values{}
|
||||||
|
s, err := convertor.StructToMap(targetStruct)
|
||||||
fieldNum := rt.NumField()
|
if err != nil {
|
||||||
pattern := `^[A-Z]`
|
return nil, err
|
||||||
regex := regexp.MustCompile(pattern)
|
}
|
||||||
for i := 0; i < fieldNum; i++ {
|
for k, v := range s {
|
||||||
name := rt.Field(i).Name
|
result.Add(k, fmt.Sprintf("%v", v))
|
||||||
tag := rt.Field(i).Tag.Get("json")
|
|
||||||
if regex.MatchString(name) && tag != "" {
|
|
||||||
result.Add(tag, fmt.Sprintf("%v", rv.Field(i).Interface()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,30 +217,31 @@ func TestStructToUrlValues(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestStructToUrlValues")
|
assert := internal.NewAssert(t, "TestStructToUrlValues")
|
||||||
|
|
||||||
type TodoQuery struct {
|
type TodoQuery struct {
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
UserId int `json:"userId"`
|
UserId int `json:"userId"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
}
|
}
|
||||||
todoQuery := TodoQuery{
|
item1 := TodoQuery{
|
||||||
Id: 1,
|
Id: 1,
|
||||||
UserId: 1,
|
UserId: 123,
|
||||||
|
Name: "",
|
||||||
|
}
|
||||||
|
todoValues, err := StructToUrlValues(item1)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("params is invalid: %v", err)
|
||||||
}
|
}
|
||||||
todoValues := StructToUrlValues(todoQuery)
|
|
||||||
|
|
||||||
assert.Equal("1", todoValues.Get("id"))
|
assert.Equal("1", todoValues.Get("id"))
|
||||||
assert.Equal("1", todoValues.Get("userId"))
|
assert.Equal("123", todoValues.Get("userId"))
|
||||||
|
assert.Equal("", todoValues.Get("name"))
|
||||||
|
|
||||||
request := &HttpRequest{
|
item2 := TodoQuery{
|
||||||
RawURL: "https://jsonplaceholder.typicode.com/todos",
|
Id: 2,
|
||||||
Method: "GET",
|
UserId: 456,
|
||||||
QueryParams: todoValues,
|
|
||||||
}
|
}
|
||||||
|
queryValues2, _ := StructToUrlValues(item2)
|
||||||
|
|
||||||
httpClient := NewHttpClient()
|
assert.Equal("2", queryValues2.Get("id"))
|
||||||
resp, err := httpClient.SendRequest(request)
|
assert.Equal("456", queryValues2.Get("userId"))
|
||||||
if err != nil || resp.StatusCode != 200 {
|
assert.Equal("", queryValues2.Get("name"))
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
body, _ := io.ReadAll(resp.Body)
|
|
||||||
t.Log("response: ", string(body))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,21 +123,45 @@ func ExampleHttpClient_DecodeResponse() {
|
|||||||
|
|
||||||
func ExampleStructToUrlValues() {
|
func ExampleStructToUrlValues() {
|
||||||
type TodoQuery struct {
|
type TodoQuery struct {
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
Name string `json:"name"`
|
UserId int `json:"userId"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Status string
|
||||||
}
|
}
|
||||||
todoQuery := TodoQuery{
|
item1 := TodoQuery{
|
||||||
Id: 1,
|
Id: 1,
|
||||||
Name: "Test",
|
UserId: 123,
|
||||||
|
Name: "test",
|
||||||
|
Status: "completed",
|
||||||
|
}
|
||||||
|
queryValues1, err := StructToUrlValues(item1)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
todoValues := StructToUrlValues(todoQuery)
|
|
||||||
|
|
||||||
fmt.Println(todoValues.Get("id"))
|
item2 := TodoQuery{
|
||||||
fmt.Println(todoValues.Get("name"))
|
Id: 2,
|
||||||
|
UserId: 456,
|
||||||
|
}
|
||||||
|
queryValues2, _ := StructToUrlValues(item2)
|
||||||
|
|
||||||
|
fmt.Println(queryValues1.Get("id"))
|
||||||
|
fmt.Println(queryValues1.Get("userId"))
|
||||||
|
fmt.Println(queryValues1.Get("name"))
|
||||||
|
fmt.Println(queryValues1.Get("status"))
|
||||||
|
|
||||||
|
fmt.Println(queryValues2.Get("id"))
|
||||||
|
fmt.Println(queryValues2.Get("userId"))
|
||||||
|
fmt.Println(queryValues2.Get("name"))
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 1
|
// 1
|
||||||
// Test
|
// 123
|
||||||
|
// test
|
||||||
|
//
|
||||||
|
// 2
|
||||||
|
// 456
|
||||||
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleConvertMapToQueryString() {
|
func ExampleConvertMapToQueryString() {
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ const (
|
|||||||
Letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
Letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
// RandInt generate random int between min and max, maybe min, not be max.
|
// RandInt generate random int between min and max, maybe min, not be max.
|
||||||
// Play: https://go.dev/play/p/pXyyAAI5YxD
|
// Play: https://go.dev/play/p/pXyyAAI5YxD
|
||||||
func RandInt(min, max int) int {
|
func RandInt(min, max int) int {
|
||||||
@@ -28,9 +32,12 @@ func RandInt(min, max int) int {
|
|||||||
if max < min {
|
if max < min {
|
||||||
min, max = max, min
|
min, max = max, min
|
||||||
}
|
}
|
||||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
||||||
|
|
||||||
return r.Intn(max-min) + min
|
// fix: https://github.com/duke-git/lancet/issues/75
|
||||||
|
// r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
// return r.Intn(max-min) + min
|
||||||
|
|
||||||
|
return rand.Intn(max-min) + min
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandBytes generate random byte slice.
|
// RandBytes generate random byte slice.
|
||||||
@@ -81,10 +88,12 @@ func RandNumeralOrLetter(length int) string {
|
|||||||
// random generate a random string based on given string range.
|
// random generate a random string based on given string range.
|
||||||
func random(s string, length int) string {
|
func random(s string, length int) string {
|
||||||
b := make([]byte, length)
|
b := make([]byte, length)
|
||||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
||||||
|
// fix: https://github.com/duke-git/lancet/issues/75
|
||||||
|
// r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
|
||||||
for i := range b {
|
for i := range b {
|
||||||
b[i] = s[r.Int63()%int64(len(s))]
|
b[i] = s[rand.Int63()%int64(len(s))]
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(b)
|
return string(b)
|
||||||
|
|||||||
@@ -33,6 +33,18 @@ func Contain[T comparable](slice []T, target T) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ContainBy returns true if predicate function return true.
|
||||||
|
// Play: https://go.dev/play/p/49tkHfX4GNc
|
||||||
|
func ContainBy[T any](slice []T, predicate func(item T) bool) bool {
|
||||||
|
for _, item := range slice {
|
||||||
|
if predicate(item) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// ContainSubSlice check if the slice contain a given subslice or not.
|
// ContainSubSlice check if the slice contain a given subslice or not.
|
||||||
// Play: https://go.dev/play/p/bcuQ3UT6Sev
|
// Play: https://go.dev/play/p/bcuQ3UT6Sev
|
||||||
func ContainSubSlice[T comparable](slice, subSlice []T) bool {
|
func ContainSubSlice[T comparable](slice, subSlice []T) bool {
|
||||||
@@ -421,6 +433,35 @@ func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilterMap returns a slice which apply both filtering and mapping to the given slice.
|
||||||
|
// iteratee callback function should returntwo values:
|
||||||
|
// 1, mapping result.
|
||||||
|
// 2, whether the result element should be included or not
|
||||||
|
// Play: https://go.dev/play/p/J94SZ_9MiIe
|
||||||
|
func FilterMap[T any, U any](slice []T, iteratee func(index int, item T) (U, bool)) []U {
|
||||||
|
result := []U{}
|
||||||
|
|
||||||
|
for i, v := range slice {
|
||||||
|
if a, ok := iteratee(i, v); ok {
|
||||||
|
result = append(result, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlatMap manipulates a slice and transforms and flattens it to a slice of another type.
|
||||||
|
// Play: https://go.dev/play/p/_QARWlWs1N_F
|
||||||
|
func FlatMap[T any, U any](slice []T, iteratee func(index int, item T) []U) []U {
|
||||||
|
result := make([]U, 0, len(slice))
|
||||||
|
|
||||||
|
for i, v := range slice {
|
||||||
|
result = append(result, iteratee(i, v)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// Reduce creates an slice of values by running each element of slice thru iteratee function.
|
// Reduce creates an slice of values by running each element of slice thru iteratee function.
|
||||||
// Play: https://go.dev/play/p/_RfXJJWIsIm
|
// Play: https://go.dev/play/p/_RfXJJWIsIm
|
||||||
func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initial T) T {
|
func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initial T) T {
|
||||||
@@ -559,7 +600,7 @@ func DeleteAt[T any](slice []T, start int, end ...int) []T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Drop drop n elements from the start of a slice.
|
// Drop drop n elements from the start of a slice.
|
||||||
// Play: https://go.dev/play/p/pJ-d6MUWcvK
|
// Play: https://go.dev/play/p/jnPO2yQsT8H
|
||||||
func Drop[T any](slice []T, n int) []T {
|
func Drop[T any](slice []T, n int) []T {
|
||||||
size := len(slice)
|
size := len(slice)
|
||||||
|
|
||||||
@@ -577,7 +618,7 @@ func Drop[T any](slice []T, n int) []T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DropRight drop n elements from the end of a slice.
|
// DropRight drop n elements from the end of a slice.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/8bcXvywZezG
|
||||||
func DropRight[T any](slice []T, n int) []T {
|
func DropRight[T any](slice []T, n int) []T {
|
||||||
size := len(slice)
|
size := len(slice)
|
||||||
|
|
||||||
@@ -595,7 +636,7 @@ func DropRight[T any](slice []T, n int) []T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DropWhile drop n elements from the start of a slice while predicate function returns true.
|
// DropWhile drop n elements from the start of a slice while predicate function returns true.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/4rt252UV_qs
|
||||||
func DropWhile[T any](slice []T, predicate func(item T) bool) []T {
|
func DropWhile[T any](slice []T, predicate func(item T) bool) []T {
|
||||||
i := 0
|
i := 0
|
||||||
|
|
||||||
@@ -611,7 +652,7 @@ func DropWhile[T any](slice []T, predicate func(item T) bool) []T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DropRightWhile drop n elements from the end of a slice while predicate function returns true.
|
// DropRightWhile drop n elements from the end of a slice while predicate function returns true.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/6wyK3zMY56e
|
||||||
func DropRightWhile[T any](slice []T, predicate func(item T) bool) []T {
|
func DropRightWhile[T any](slice []T, predicate func(item T) bool) []T {
|
||||||
i := len(slice) - 1
|
i := len(slice) - 1
|
||||||
|
|
||||||
@@ -831,7 +872,7 @@ func Shuffle[T any](slice []T) []T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsAscending checks if a slice is ascending order.
|
// IsAscending checks if a slice is ascending order.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/9CtsFjet4SH
|
||||||
func IsAscending[T constraints.Ordered](slice []T) bool {
|
func IsAscending[T constraints.Ordered](slice []T) bool {
|
||||||
for i := 1; i < len(slice); i++ {
|
for i := 1; i < len(slice); i++ {
|
||||||
if slice[i-1] > slice[i] {
|
if slice[i-1] > slice[i] {
|
||||||
@@ -843,7 +884,7 @@ func IsAscending[T constraints.Ordered](slice []T) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsDescending checks if a slice is descending order.
|
// IsDescending checks if a slice is descending order.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/U_LljFXma14
|
||||||
func IsDescending[T constraints.Ordered](slice []T) bool {
|
func IsDescending[T constraints.Ordered](slice []T) bool {
|
||||||
for i := 1; i < len(slice); i++ {
|
for i := 1; i < len(slice); i++ {
|
||||||
if slice[i-1] < slice[i] {
|
if slice[i-1] < slice[i] {
|
||||||
@@ -855,13 +896,13 @@ func IsDescending[T constraints.Ordered](slice []T) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsSorted checks if a slice is sorted(ascending or descending).
|
// IsSorted checks if a slice is sorted(ascending or descending).
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/nCE8wPLwSA-
|
||||||
func IsSorted[T constraints.Ordered](slice []T) bool {
|
func IsSorted[T constraints.Ordered](slice []T) bool {
|
||||||
return IsAscending(slice) || IsDescending(slice)
|
return IsAscending(slice) || IsDescending(slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSortedByKey checks if a slice is sorted by iteratee function.
|
// IsSortedByKey checks if a slice is sorted by iteratee function.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/tUoGB7DOHI4
|
||||||
func IsSortedByKey[T any, K constraints.Ordered](slice []T, iteratee func(item T) K) bool {
|
func IsSortedByKey[T any, K constraints.Ordered](slice []T, iteratee func(item T) K) bool {
|
||||||
size := len(slice)
|
size := len(slice)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleContain() {
|
func ExampleContain() {
|
||||||
@@ -18,6 +19,32 @@ func ExampleContain() {
|
|||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleContainBy() {
|
||||||
|
type foo struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
}
|
||||||
|
|
||||||
|
array1 := []foo{{A: "1", B: 1}, {A: "2", B: 2}}
|
||||||
|
result1 := ContainBy(array1, func(f foo) bool { return f.A == "1" && f.B == 1 })
|
||||||
|
result2 := ContainBy(array1, func(f foo) bool { return f.A == "2" && f.B == 1 })
|
||||||
|
|
||||||
|
array2 := []string{"a", "b", "c"}
|
||||||
|
result3 := ContainBy(array2, func(t string) bool { return t == "a" })
|
||||||
|
result4 := ContainBy(array2, func(t string) bool { return t == "d" })
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleContainSubSlice() {
|
func ExampleContainSubSlice() {
|
||||||
result1 := ContainSubSlice([]string{"a", "b", "c"}, []string{"a", "b"})
|
result1 := ContainSubSlice([]string{"a", "b", "c"}, []string{"a", "b"})
|
||||||
result2 := ContainSubSlice([]string{"a", "b", "c"}, []string{"a", "d"})
|
result2 := ContainSubSlice([]string{"a", "b", "c"}, []string{"a", "d"})
|
||||||
@@ -367,6 +394,38 @@ func ExampleMap() {
|
|||||||
// [2 3 4]
|
// [2 3 4]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleFilterMap() {
|
||||||
|
nums := []int{1, 2, 3, 4, 5}
|
||||||
|
|
||||||
|
getEvenNumStr := func(i, num int) (string, bool) {
|
||||||
|
if num%2 == 0 {
|
||||||
|
return strconv.FormatInt(int64(num), 10), true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
result := FilterMap(nums, getEvenNumStr)
|
||||||
|
|
||||||
|
fmt.Printf("%#v", result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []string{"2", "4"}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleFlatMap() {
|
||||||
|
nums := []int{1, 2, 3, 4}
|
||||||
|
|
||||||
|
result := FlatMap(nums, func(i int, num int) []string {
|
||||||
|
s := "hi-" + strconv.FormatInt(int64(num), 10)
|
||||||
|
return []string{s}
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Printf("%#v", result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []string{"hi-1", "hi-2", "hi-3", "hi-4"}
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleReduce() {
|
func ExampleReduce() {
|
||||||
nums := []int{1, 2, 3}
|
nums := []int{1, 2, 3}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package slice
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/v2/internal"
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
@@ -19,6 +20,28 @@ func TestContain(t *testing.T) {
|
|||||||
assert.Equal(true, Contain([]int{1, 2, 3}, 1))
|
assert.Equal(true, Contain([]int{1, 2, 3}, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContainBy(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestContainBy")
|
||||||
|
|
||||||
|
type foo struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
}
|
||||||
|
|
||||||
|
array1 := []foo{{A: "1", B: 1}, {A: "2", B: 2}}
|
||||||
|
result1 := ContainBy(array1, func(f foo) bool { return f.A == "1" && f.B == 1 })
|
||||||
|
result2 := ContainBy(array1, func(f foo) bool { return f.A == "2" && f.B == 1 })
|
||||||
|
|
||||||
|
array2 := []string{"a", "b", "c"}
|
||||||
|
result3 := ContainBy(array2, func(t string) bool { return t == "a" })
|
||||||
|
result4 := ContainBy(array2, func(t string) bool { return t == "d" })
|
||||||
|
|
||||||
|
assert.Equal(true, result1)
|
||||||
|
assert.Equal(false, result2)
|
||||||
|
assert.Equal(true, result3)
|
||||||
|
assert.Equal(false, result4)
|
||||||
|
}
|
||||||
|
|
||||||
func TestContainSubSlice(t *testing.T) {
|
func TestContainSubSlice(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestContainSubSlice")
|
assert := internal.NewAssert(t, "TestContainSubSlice")
|
||||||
assert.Equal(true, ContainSubSlice([]string{"a", "a", "b", "c"}, []string{"a", "a"}))
|
assert.Equal(true, ContainSubSlice([]string{"a", "a", "b", "c"}, []string{"a", "a"}))
|
||||||
@@ -315,6 +338,36 @@ func TestMap(t *testing.T) {
|
|||||||
assert.Equal(studentsOfAdd10Aage, Map(students, mapFunc))
|
assert.Equal(studentsOfAdd10Aage, Map(students, mapFunc))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFilterMap(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestFilterMap")
|
||||||
|
|
||||||
|
nums := []int{1, 2, 3, 4, 5}
|
||||||
|
|
||||||
|
getEvenNumStr := func(i, num int) (string, bool) {
|
||||||
|
if num%2 == 0 {
|
||||||
|
return strconv.FormatInt(int64(num), 10), true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
result := FilterMap(nums, getEvenNumStr)
|
||||||
|
|
||||||
|
assert.Equal([]string{"2", "4"}, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFlatMap(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestFlatMap")
|
||||||
|
|
||||||
|
nums := []int{1, 2, 3, 4}
|
||||||
|
|
||||||
|
result := FlatMap(nums, func(i int, num int) []string {
|
||||||
|
s := "hi-" + strconv.FormatInt(int64(num), 10)
|
||||||
|
return []string{s}
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal([]string{"hi-1", "hi-2", "hi-3", "hi-4"}, result)
|
||||||
|
}
|
||||||
|
|
||||||
func TestReduce(t *testing.T) {
|
func TestReduce(t *testing.T) {
|
||||||
cases := [][]int{
|
cases := [][]int{
|
||||||
{},
|
{},
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ func Generate[T any](generator func() func() (item T, ok bool)) stream[T] {
|
|||||||
|
|
||||||
var zeroValue T
|
var zeroValue T
|
||||||
for next, item, ok := generator(), zeroValue, true; ok; {
|
for next, item, ok := generator(), zeroValue, true; ok; {
|
||||||
|
|
||||||
item, ok = next()
|
item, ok = next()
|
||||||
if ok {
|
if ok {
|
||||||
source = append(source, item)
|
source = append(source, item)
|
||||||
@@ -98,7 +99,7 @@ func FromRange[T constraints.Integer | constraints.Float](start, end, step T) st
|
|||||||
}
|
}
|
||||||
|
|
||||||
l := int((end-start)/step) + 1
|
l := int((end-start)/step) + 1
|
||||||
source := make([]T, l, l)
|
source := make([]T, l)
|
||||||
|
|
||||||
for i := 0; i < l; i++ {
|
for i := 0; i < l; i++ {
|
||||||
source[i] = start + (T(i) * step)
|
source[i] = start + (T(i) * step)
|
||||||
@@ -160,7 +161,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.
|
||||||
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(), s.Count())
|
source := make([]T, s.Count())
|
||||||
|
|
||||||
for i, v := range s.source {
|
for i, v := range s.source {
|
||||||
source[i] = mapper(v)
|
source[i] = mapper(v)
|
||||||
|
|||||||
55
structutil/field.go
Normal file
55
structutil/field.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package structutil
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
type Field struct {
|
||||||
|
value reflect.Value
|
||||||
|
field reflect.StructField
|
||||||
|
tag *Tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func newField(v reflect.Value, f reflect.StructField, tagName string) *Field {
|
||||||
|
tag := f.Tag.Get(tagName)
|
||||||
|
return &Field{
|
||||||
|
value: v,
|
||||||
|
field: f,
|
||||||
|
tag: newTag(tag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tag returns the value that the key in the tag string.
|
||||||
|
func (f *Field) Tag() *Tag {
|
||||||
|
return f.tag
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the underlying value of the field.
|
||||||
|
func (f *Field) Value() any {
|
||||||
|
return f.value.Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmbedded returns true if the given field is an embedded field.
|
||||||
|
func (f *Field) IsEmbedded() bool {
|
||||||
|
return f.field.Anonymous
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsExported returns true if the given field is exported.
|
||||||
|
func (f *Field) IsExported() bool {
|
||||||
|
return f.field.PkgPath == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsZero returns true if the given field is zero value.
|
||||||
|
func (f *Field) IsZero() bool {
|
||||||
|
z := reflect.Zero(f.value.Type()).Interface()
|
||||||
|
v := f.Value()
|
||||||
|
return reflect.DeepEqual(z, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the name of the given field
|
||||||
|
func (f *Field) Name() string {
|
||||||
|
return f.field.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns the field's kind
|
||||||
|
func (f *Field) Kind() reflect.Kind {
|
||||||
|
return f.value.Kind()
|
||||||
|
}
|
||||||
88
structutil/struct.go
Normal file
88
structutil/struct.go
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
package structutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultTagName is the default tag for struct fields to lookup.
|
||||||
|
var DefaultTagName = "json"
|
||||||
|
|
||||||
|
// Struct is abstract struct for provide several high level functions
|
||||||
|
type Struct struct {
|
||||||
|
raw any
|
||||||
|
rtype reflect.Type
|
||||||
|
rvalue reflect.Value
|
||||||
|
TagName string
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new *Struct
|
||||||
|
func New(value any) *Struct {
|
||||||
|
v := reflect.ValueOf(value)
|
||||||
|
t := reflect.TypeOf(value)
|
||||||
|
if v.Kind() == reflect.Ptr {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
return &Struct{
|
||||||
|
raw: value,
|
||||||
|
rtype: t,
|
||||||
|
rvalue: v,
|
||||||
|
TagName: DefaultTagName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToMap converts the given struct to a map[string]any, where the keys
|
||||||
|
// of the keys are the field names and the values of the map are the values
|
||||||
|
// of the fields. The default map key is the struct field name, but you can
|
||||||
|
// change it. The `json` key is the default tag key. Example:
|
||||||
|
//
|
||||||
|
// // default
|
||||||
|
// Name string `json:"name"`
|
||||||
|
//
|
||||||
|
// // ignore the field
|
||||||
|
// Name string // no tag
|
||||||
|
// Age string `json:"-"` // json ignore tag
|
||||||
|
// sex string // unexported field
|
||||||
|
// Goal int `json:"goal,omitempty"` // omitempty if the field is zero value
|
||||||
|
//
|
||||||
|
// // custom map key
|
||||||
|
// Name string `json:"myName"`
|
||||||
|
//
|
||||||
|
// Only the exported fields of a struct can be converted.
|
||||||
|
func (s *Struct) ToMap() (map[string]any, error) {
|
||||||
|
result := make(map[string]any)
|
||||||
|
|
||||||
|
fields := s.Fields()
|
||||||
|
for _, f := range fields {
|
||||||
|
if !f.IsExported() || f.tag.IsEmpty() || f.tag.Name == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if f.IsZero() && f.tag.HasOption("omitempty") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// TODO: sub struct
|
||||||
|
result[f.tag.Name] = f.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fields returns all the struct fields within a slice
|
||||||
|
func (s *Struct) Fields() []*Field {
|
||||||
|
|
||||||
|
var fields []*Field
|
||||||
|
fieldNum := s.rvalue.NumField()
|
||||||
|
for i := 0; i < fieldNum; i++ {
|
||||||
|
v := s.rvalue.Field(i)
|
||||||
|
sf := s.rtype.Field(i)
|
||||||
|
field := newField(v, sf, DefaultTagName)
|
||||||
|
fields = append(fields, field)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToMap convert struct to map, only convert exported struct field
|
||||||
|
// map key is specified same as struct field tag `json` value.
|
||||||
|
func ToMap(v any) (map[string]any, error) {
|
||||||
|
return New(v).ToMap()
|
||||||
|
}
|
||||||
57
structutil/struct_test.go
Normal file
57
structutil/struct_test.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package structutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestToMap(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestStructToMap")
|
||||||
|
|
||||||
|
t.Run("StructToMap", func(_ *testing.T) {
|
||||||
|
type People struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
age int
|
||||||
|
}
|
||||||
|
p := People{
|
||||||
|
"test",
|
||||||
|
100,
|
||||||
|
}
|
||||||
|
pm, _ := ToMap(p)
|
||||||
|
var expected = map[string]any{"name": "test"}
|
||||||
|
assert.Equal(expected, pm)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("StructToMapWithJsonAttr", func(_ *testing.T) {
|
||||||
|
type People struct {
|
||||||
|
Name string `json:"name,omitempty"` // json tag with attribute
|
||||||
|
Phone string `json:"phone"` // json tag without attribute
|
||||||
|
Sex string `json:"-"` // ignore by "-"
|
||||||
|
Age int // ignore by no tag
|
||||||
|
email string // ignore by unexported
|
||||||
|
IsWorking bool `json:"is_working"`
|
||||||
|
}
|
||||||
|
p1 := People{
|
||||||
|
Name: "AAA", // exist
|
||||||
|
Phone: "1111",
|
||||||
|
Sex: "male",
|
||||||
|
Age: 100,
|
||||||
|
email: "11@gmail.com",
|
||||||
|
}
|
||||||
|
p1m, _ := ToMap(p1)
|
||||||
|
var expect1 = map[string]any{"name": "AAA", "phone": "1111", "is_working": false}
|
||||||
|
assert.Equal(expect1, p1m)
|
||||||
|
|
||||||
|
p2 := People{
|
||||||
|
Name: "",
|
||||||
|
Phone: "2222",
|
||||||
|
Sex: "male",
|
||||||
|
Age: 0,
|
||||||
|
email: "22@gmail.com",
|
||||||
|
IsWorking: true,
|
||||||
|
}
|
||||||
|
p2m, _ := ToMap(p2)
|
||||||
|
var expect2 = map[string]any{"phone": "2222", "is_working": true}
|
||||||
|
assert.Equal(expect2, p2m)
|
||||||
|
})
|
||||||
|
}
|
||||||
32
structutil/tag.go
Normal file
32
structutil/tag.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package structutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Tag struct {
|
||||||
|
Name string
|
||||||
|
Options []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTag(tag string) *Tag {
|
||||||
|
res := strings.Split(tag, ",")
|
||||||
|
return &Tag{
|
||||||
|
Name: res[0],
|
||||||
|
Options: res[1:],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tag) HasOption(opt string) bool {
|
||||||
|
for _, o := range t.Options {
|
||||||
|
if o == opt {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tag) IsEmpty() bool {
|
||||||
|
return validator.IsEmptyString(t.Name)
|
||||||
|
}
|
||||||
@@ -67,44 +67,25 @@ func LowerFirst(s string) string {
|
|||||||
return string(r) + s[size:]
|
return string(r) + s[size:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// PadEnd pads string on the right side if it's shorter than size.
|
// PadStart pads string on the left and right side if it's shorter than size.
|
||||||
// Padding characters are truncated if they exceed size.
|
// Padding characters are truncated if they exceed size.
|
||||||
// Play: https://go.dev/play/p/9xP8rN0vz--
|
// Play: https://go.dev/play/p/NzImQq-VF8q
|
||||||
func PadEnd(source string, size int, padStr string) string {
|
func Pad(source string, size int, padStr string) string {
|
||||||
len1 := len(source)
|
return padAtPosition(source, size, padStr, 0)
|
||||||
len2 := len(padStr)
|
|
||||||
|
|
||||||
if len1 >= size {
|
|
||||||
return source
|
|
||||||
}
|
|
||||||
|
|
||||||
fill := ""
|
|
||||||
if len2 >= size-len1 {
|
|
||||||
fill = padStr[0 : size-len1]
|
|
||||||
} else {
|
|
||||||
fill = strings.Repeat(padStr, size-len1)
|
|
||||||
}
|
|
||||||
return source + fill[0:size-len1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PadStart pads string on the left side if it's shorter than size.
|
// PadStart pads string on the left side if it's shorter than size.
|
||||||
// Padding characters are truncated if they exceed size.
|
// Padding characters are truncated if they exceed size.
|
||||||
// Play: https://go.dev/play/p/xpTfzArDfvT
|
// Play: https://go.dev/play/p/xpTfzArDfvT
|
||||||
func PadStart(source string, size int, padStr string) string {
|
func PadStart(source string, size int, padStr string) string {
|
||||||
len1 := len(source)
|
return padAtPosition(source, size, padStr, 1)
|
||||||
len2 := len(padStr)
|
}
|
||||||
|
|
||||||
if len1 >= size {
|
// PadEnd pads string on the right side if it's shorter than size.
|
||||||
return source
|
// Padding characters are truncated if they exceed size.
|
||||||
}
|
// Play: https://go.dev/play/p/9xP8rN0vz--
|
||||||
|
func PadEnd(source string, size int, padStr string) string {
|
||||||
fill := ""
|
return padAtPosition(source, size, padStr, 2)
|
||||||
if len2 >= size-len1 {
|
|
||||||
fill = padStr[0 : size-len1]
|
|
||||||
} else {
|
|
||||||
fill = strings.Repeat(padStr, size-len1)
|
|
||||||
}
|
|
||||||
return fill[0:size-len1] + source
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// KebabCase coverts string to kebab-case, non letters and numbers will be ignored.
|
// KebabCase coverts string to kebab-case, non letters and numbers will be ignored.
|
||||||
@@ -306,3 +287,76 @@ func Substring(s string, offset int, length uint) string {
|
|||||||
|
|
||||||
return strings.Replace(str, "\x00", "", -1)
|
return strings.Replace(str, "\x00", "", -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SplitWords splits a string into words, word only contains alphabetic characters.
|
||||||
|
// Play: https://go.dev/play/p/KLiX4WiysMM
|
||||||
|
func SplitWords(s string) []string {
|
||||||
|
var word string
|
||||||
|
var words []string
|
||||||
|
var r rune
|
||||||
|
var size, pos int
|
||||||
|
|
||||||
|
isWord := false
|
||||||
|
|
||||||
|
for len(s) > 0 {
|
||||||
|
r, size = utf8.DecodeRuneInString(s)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case isLetter(r):
|
||||||
|
if !isWord {
|
||||||
|
isWord = true
|
||||||
|
word = s
|
||||||
|
pos = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
case isWord && (r == '\'' || r == '-'):
|
||||||
|
// is word
|
||||||
|
|
||||||
|
default:
|
||||||
|
if isWord {
|
||||||
|
isWord = false
|
||||||
|
words = append(words, word[:pos])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += size
|
||||||
|
s = s[size:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if isWord {
|
||||||
|
words = append(words, word[:pos])
|
||||||
|
}
|
||||||
|
|
||||||
|
return words
|
||||||
|
}
|
||||||
|
|
||||||
|
// WordCount return the number of meaningful word, word only contains alphabetic characters.
|
||||||
|
// Play: https://go.dev/play/p/bj7_odx3vRf
|
||||||
|
func WordCount(s string) int {
|
||||||
|
var r rune
|
||||||
|
var size, count int
|
||||||
|
|
||||||
|
isWord := false
|
||||||
|
|
||||||
|
for len(s) > 0 {
|
||||||
|
r, size = utf8.DecodeRuneInString(s)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case isLetter(r):
|
||||||
|
if !isWord {
|
||||||
|
isWord = true
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
|
||||||
|
case isWord && (r == '\'' || r == '-'):
|
||||||
|
// is word
|
||||||
|
|
||||||
|
default:
|
||||||
|
isWord = false
|
||||||
|
}
|
||||||
|
|
||||||
|
s = s[size:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|||||||
@@ -186,6 +186,33 @@ func ExampleUpperFirst() {
|
|||||||
// Bar大
|
// Bar大
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExamplePad() {
|
||||||
|
result1 := Pad("foo", 1, "bar")
|
||||||
|
result2 := Pad("foo", 2, "bar")
|
||||||
|
result3 := Pad("foo", 3, "bar")
|
||||||
|
result4 := Pad("foo", 4, "bar")
|
||||||
|
result5 := Pad("foo", 5, "bar")
|
||||||
|
result6 := Pad("foo", 6, "bar")
|
||||||
|
result7 := Pad("foo", 7, "bar")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
fmt.Println(result7)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// foo
|
||||||
|
// foo
|
||||||
|
// foo
|
||||||
|
// foob
|
||||||
|
// bfoob
|
||||||
|
// bfooba
|
||||||
|
// bafooba
|
||||||
|
}
|
||||||
|
|
||||||
func ExamplePadEnd() {
|
func ExamplePadEnd() {
|
||||||
result1 := PadEnd("foo", 1, "bar")
|
result1 := PadEnd("foo", 1, "bar")
|
||||||
result2 := PadEnd("foo", 2, "bar")
|
result2 := PadEnd("foo", 2, "bar")
|
||||||
@@ -361,3 +388,53 @@ func ExampleSubstring() {
|
|||||||
// de
|
// de
|
||||||
// 你好
|
// 你好
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleSplitWords() {
|
||||||
|
|
||||||
|
result1 := SplitWords("a word")
|
||||||
|
result2 := SplitWords("I'am a programmer")
|
||||||
|
result3 := SplitWords("Bonjour, je suis programmeur")
|
||||||
|
result4 := SplitWords("a -b-c' 'd'e")
|
||||||
|
result5 := SplitWords("你好,我是一名码农")
|
||||||
|
result6 := SplitWords("こんにちは,私はプログラマーです")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [a word]
|
||||||
|
// [I'am a programmer]
|
||||||
|
// [Bonjour je suis programmeur]
|
||||||
|
// [a b-c' d'e]
|
||||||
|
// []
|
||||||
|
// []
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleWordCount() {
|
||||||
|
|
||||||
|
result1 := WordCount("a word")
|
||||||
|
result2 := WordCount("I'am a programmer")
|
||||||
|
result3 := WordCount("Bonjour, je suis programmeur")
|
||||||
|
result4 := WordCount("a -b-c' 'd'e")
|
||||||
|
result5 := WordCount("你好,我是一名码农")
|
||||||
|
result6 := WordCount("こんにちは,私はプログラマーです")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 2
|
||||||
|
// 3
|
||||||
|
// 4
|
||||||
|
// 3
|
||||||
|
// 0
|
||||||
|
// 0
|
||||||
|
}
|
||||||
|
|||||||
@@ -98,3 +98,73 @@ func toUpperAll(rs []rune) []rune {
|
|||||||
}
|
}
|
||||||
return rs
|
return rs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// padWithPosition pads string
|
||||||
|
func padAtPosition(str string, length int, padStr string, position int) string {
|
||||||
|
if len(str) >= length {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
if padStr == "" {
|
||||||
|
padStr = " "
|
||||||
|
}
|
||||||
|
|
||||||
|
length = length - len(str)
|
||||||
|
startPadLen := 0
|
||||||
|
if position == 0 {
|
||||||
|
startPadLen = length / 2
|
||||||
|
} else if position == 1 {
|
||||||
|
startPadLen = length
|
||||||
|
}
|
||||||
|
endPadLen := length - startPadLen
|
||||||
|
|
||||||
|
charLen := len(padStr)
|
||||||
|
leftPad := ""
|
||||||
|
cur := 0
|
||||||
|
for cur < startPadLen {
|
||||||
|
leftPad += string(padStr[cur%charLen])
|
||||||
|
cur++
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = 0
|
||||||
|
rightPad := ""
|
||||||
|
for cur < endPadLen {
|
||||||
|
rightPad += string(padStr[cur%charLen])
|
||||||
|
cur++
|
||||||
|
}
|
||||||
|
|
||||||
|
return leftPad + str + rightPad
|
||||||
|
}
|
||||||
|
|
||||||
|
// isLetter checks r is a letter but not CJK character.
|
||||||
|
func isLetter(r rune) bool {
|
||||||
|
if !unicode.IsLetter(r) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
// cjk char: /[\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff\uff66-\uff9f]/
|
||||||
|
|
||||||
|
// hiragana and katakana (Japanese only)
|
||||||
|
case r >= '\u3034' && r < '\u30ff':
|
||||||
|
return false
|
||||||
|
|
||||||
|
// CJK unified ideographs extension A (Chinese, Japanese, and Korean)
|
||||||
|
case r >= '\u3400' && r < '\u4dbf':
|
||||||
|
return false
|
||||||
|
|
||||||
|
// CJK unified ideographs (Chinese, Japanese, and Korean)
|
||||||
|
case r >= '\u4e00' && r < '\u9fff':
|
||||||
|
return false
|
||||||
|
|
||||||
|
// CJK compatibility ideographs (Chinese, Japanese, and Korean)
|
||||||
|
case r >= '\uf900' && r < '\ufaff':
|
||||||
|
return false
|
||||||
|
|
||||||
|
// half-width katakana (Japanese only)
|
||||||
|
case r >= '\uff66' && r < '\uff9f':
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -168,9 +168,19 @@ func TestLowerFirst(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPad(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestPad")
|
||||||
|
|
||||||
|
assert.Equal("a ", Pad("a", 2, ""))
|
||||||
|
assert.Equal("a", Pad("a", 1, "b"))
|
||||||
|
assert.Equal("ab", Pad("a", 2, "b"))
|
||||||
|
assert.Equal("mabcdm", Pad("abcd", 6, "m"))
|
||||||
|
}
|
||||||
|
|
||||||
func TestPadEnd(t *testing.T) {
|
func TestPadEnd(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestPadEnd")
|
assert := internal.NewAssert(t, "TestPadEnd")
|
||||||
|
|
||||||
|
assert.Equal("a ", PadEnd("a", 2, " "))
|
||||||
assert.Equal("a", PadEnd("a", 1, "b"))
|
assert.Equal("a", PadEnd("a", 1, "b"))
|
||||||
assert.Equal("ab", PadEnd("a", 2, "b"))
|
assert.Equal("ab", PadEnd("a", 2, "b"))
|
||||||
assert.Equal("abcdmn", PadEnd("abcd", 6, "mno"))
|
assert.Equal("abcdmn", PadEnd("abcd", 6, "mno"))
|
||||||
@@ -298,3 +308,37 @@ func TestSubstring(t *testing.T) {
|
|||||||
assert.Equal("de", Substring("abcde", -2, 3))
|
assert.Equal("de", Substring("abcde", -2, 3))
|
||||||
assert.Equal("你好", Substring("你好,欢迎你", 0, 2))
|
assert.Equal("你好", Substring("你好,欢迎你", 0, 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSplitWords(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSplitWords")
|
||||||
|
|
||||||
|
cases := map[string][]string{
|
||||||
|
"a word": {"a", "word"},
|
||||||
|
"I'am a programmer": {"I'am", "a", "programmer"},
|
||||||
|
"Bonjour, je suis programmeur": {"Bonjour", "je", "suis", "programmeur"},
|
||||||
|
"a -b-c' 'd'e": {"a", "b-c'", "d'e"},
|
||||||
|
"你好,我是一名码农": nil,
|
||||||
|
"こんにちは,私はプログラマーです": nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range cases {
|
||||||
|
assert.Equal(v, SplitWords(k))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWordCount(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSplitWords")
|
||||||
|
|
||||||
|
cases := map[string]int{
|
||||||
|
"a word": 2, // {"a", "word"},
|
||||||
|
"I'am a programmer": 3, // {"I'am", "a", "programmer"},
|
||||||
|
"Bonjour, je suis programmeur": 4, // {"Bonjour", "je", "suis", "programmeur"},
|
||||||
|
"a -b-c' 'd'e": 3, // {"a", "b-c'", "d'e"},
|
||||||
|
"你好,我是一名码农": 0, // nil,
|
||||||
|
"こんにちは,私はプログラマーです": 0, // nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range cases {
|
||||||
|
assert.Equal(v, WordCount(k))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user