mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-05 05:12:26 +08:00
Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac0fb5ef25 | ||
|
|
9bd1c205fe | ||
|
|
6ccf9fd3cf | ||
|
|
c02ef2c62d | ||
|
|
6414031754 | ||
|
|
5336130570 | ||
|
|
bfa46d46a2 | ||
|
|
aab28b914c | ||
|
|
336e454ce7 | ||
|
|
35a50bd792 | ||
|
|
2fd23f02f6 | ||
|
|
aad5b447c9 | ||
|
|
cece13e929 | ||
|
|
ecf325a06c | ||
|
|
44370aef5e | ||
|
|
1782b11ec4 | ||
|
|
fe6495123c | ||
|
|
d442f564ce | ||
|
|
f35446cc13 | ||
|
|
506a8b4776 | ||
|
|
47ecfbfd5f | ||
|
|
82f7401368 | ||
|
|
068c878d1e | ||
|
|
47b2402345 | ||
|
|
a245716f99 | ||
|
|
71c85bb8f0 | ||
|
|
5edafec393 | ||
|
|
957878dd98 | ||
|
|
12e979cf3c | ||
|
|
ded42f8ff5 | ||
|
|
d06cde3fcf | ||
|
|
9cd8bfb8e0 | ||
|
|
51c9877224 | ||
|
|
f7f6427919 | ||
|
|
56b6844a2d | ||
|
|
cce56f0479 | ||
|
|
3dbd7d8980 | ||
|
|
3625921912 | ||
|
|
1faaf54986 | ||
|
|
efe1fba267 | ||
|
|
0c43cb3f68 | ||
|
|
c25111e349 | ||
|
|
a61ab5716e | ||
|
|
628404dc7f | ||
|
|
bab0a27e40 | ||
|
|
fc0e104591 | ||
|
|
e83e9a1651 | ||
|
|
3d2e6295c4 | ||
|
|
221fe44e63 | ||
|
|
7930f517ae | ||
|
|
0f61321d5b | ||
|
|
7ddeeb51e5 | ||
|
|
484d2845b3 | ||
|
|
bbbc6b6941 | ||
|
|
acf028cdcd | ||
|
|
31e43ec356 | ||
|
|
9f45e68fef | ||
|
|
d2df99a6f0 | ||
|
|
713c341831 | ||
|
|
0b05a6dd6f | ||
|
|
d21c101caf | ||
|
|
bf49db60d9 | ||
|
|
d57fa3b603 | ||
|
|
b3a29ce82d | ||
|
|
1d8a37d6e8 | ||
|
|
ef2d8e14b0 | ||
|
|
0cbb3dd97e | ||
|
|
38a7f9423f | ||
|
|
2c0ab9e922 | ||
|
|
9aa3b742ff | ||
|
|
6bfaba750d | ||
|
|
69f8bee935 | ||
|
|
07d04a9cd0 | ||
|
|
6f17ba9116 | ||
|
|
56d1e5e95c | ||
|
|
11d86d0270 | ||
|
|
d1c20a1da8 | ||
|
|
f87ab89207 | ||
|
|
9ebb0c7920 | ||
|
|
31a5ed11a3 | ||
|
|
a706d488e6 | ||
|
|
61251fb0f1 | ||
|
|
747dc30b02 | ||
|
|
d54f27d9a9 | ||
|
|
dbca2f6be4 | ||
|
|
2ef9b56d22 | ||
|
|
52ecde7e24 | ||
|
|
a7dce5e4d3 | ||
|
|
4718da44f4 | ||
|
|
1aa1f95524 | ||
|
|
d922b2e778 | ||
|
|
5a7b3c4a37 | ||
|
|
1c2b1a2f02 | ||
|
|
c68440ecf8 | ||
|
|
6a48b3f99e | ||
|
|
bab9ae32d4 | ||
|
|
f0e6e94c5e | ||
|
|
a6fe155781 | ||
|
|
d5be9009fc | ||
|
|
ca47be41f6 | ||
|
|
ff5db30208 | ||
|
|
a429d46072 | ||
|
|
7b84fbfd94 | ||
|
|
fc6f618885 | ||
|
|
7f03c3b0a2 | ||
|
|
4b4386bd47 | ||
|
|
10a1706613 | ||
|
|
d097f356fd | ||
|
|
bc9bacaa55 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,4 +6,5 @@ fileutil/*.txt
|
||||
fileutil/*.zip
|
||||
fileutil/*.link
|
||||
fileutil/unzip/*
|
||||
slice/testdata/*
|
||||
cryptor/*.pem
|
||||
77
README.md
77
README.md
@@ -3,8 +3,8 @@
|
||||
|
||||
<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://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
@@ -35,9 +35,9 @@ English | [简体中文](./README_zh-CN.md)
|
||||
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. now latest v1 is v1.2.9. </b>
|
||||
2. <b>For users who use version below go1.18, you should install v1.x.x. now latest v1 is v1.3.0. </b>
|
||||
```go
|
||||
go get github.com/duke-git/lancet@v1.2.9 // below go1.18, install latest version of v1.x.x
|
||||
go get github.com/duke-git/lancet@v1.3.0 // below go1.18, install latest version of v1.x.x
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -118,10 +118,15 @@ import "github.com/duke-git/lancet/v2/convertor"
|
||||
- [ToBool](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBool)
|
||||
- [ToBytes](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBytes)
|
||||
- [ToChar](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChar)
|
||||
- [ToChannel](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChannel)
|
||||
- [ToFloat](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToFloat)
|
||||
- [ToInt](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToInt)
|
||||
- [ToJson](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToJson)
|
||||
- [ToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToMap)
|
||||
- [ToPointer](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToPointer)
|
||||
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToString)
|
||||
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#StructToMap)
|
||||
- [MapToSlice](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#MapToSlice)
|
||||
|
||||
### 4. Cryptor package is for data encryption and decryption.
|
||||
|
||||
@@ -201,7 +206,31 @@ import "github.com/duke-git/lancet/v2/datetime"
|
||||
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormatForTpl)
|
||||
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)
|
||||
|
||||
### 6. Fileutil package implements some basic functions for file operations.
|
||||
|
||||
|
||||
### 6. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph.
|
||||
|
||||
|
||||
```go
|
||||
import list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
import link "github.com/duke-git/lancet/v2/datastructure/link"
|
||||
import stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
import queue "github.com/duke-git/lancet/v2/datastructure/queue"
|
||||
import set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
import tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
import heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
```
|
||||
#### Function list:
|
||||
- [List](https://github.com/duke-git/lancet/blob/main/docs/datastructure/list.md)
|
||||
- [Linklist](https://github.com/duke-git/lancet/blob/main/docs/datastructure/linklist.md)
|
||||
- [Stack](https://github.com/duke-git/lancet/blob/main/docs/datastructure/stack.md)
|
||||
- [Queue](https://github.com/duke-git/lancet/blob/main/docs/datastructure/queue.md)
|
||||
- [Set](https://github.com/duke-git/lancet/blob/main/docs/datastructure/set.md)
|
||||
- [Tree](https://github.com/duke-git/lancet/blob/main/docs/datastructure/tree.md)
|
||||
- [Heap](https://github.com/duke-git/lancet/blob/main/docs/datastructure/heap.md)
|
||||
|
||||
|
||||
### 7. Fileutil package implements some basic functions for file operations.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/fileutil"
|
||||
@@ -211,6 +240,7 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
|
||||
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ClearFile)
|
||||
- [CreateFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CreateFile)
|
||||
- [CreateDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CreateDir)
|
||||
- [CopyFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CopyFile)
|
||||
- [FileMode](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#FileMode)
|
||||
- [MiMeType](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#MiMeType)
|
||||
@@ -224,7 +254,7 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Zip)
|
||||
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)
|
||||
|
||||
### 7. Formatter contains some functions for data formatting.
|
||||
### 8. Formatter contains some functions for data formatting.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/formatter"
|
||||
@@ -232,7 +262,7 @@ import "github.com/duke-git/lancet/v2/formatter"
|
||||
#### Function list:
|
||||
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma)
|
||||
|
||||
### 8. Function package can control the flow of function execution and support part of functional programming
|
||||
### 9. Function package can control the flow of function execution and support part of functional programming
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/function"
|
||||
@@ -248,7 +278,7 @@ import "github.com/duke-git/lancet/v2/function"
|
||||
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)
|
||||
|
||||
|
||||
### 9. Maputil package includes some functions to manipulate map.
|
||||
### 10. Maputil package includes some functions to manipulate map.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/maputil"
|
||||
@@ -262,9 +292,10 @@ import "github.com/duke-git/lancet/v2/maputil"
|
||||
- [Merge](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Merge)
|
||||
- [Minus](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Minus)
|
||||
- [Values](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Values)
|
||||
- [IsDisjoint](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#IsDisjoint)
|
||||
|
||||
|
||||
### 10. Mathutil package implements some functions for math calculation.
|
||||
### 11. Mathutil package implements some functions for math calculation.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/mathutil"
|
||||
@@ -285,7 +316,7 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
||||
- [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#TruncRound)
|
||||
|
||||
|
||||
### 11. Netutil package contains functions to get net information and send http request.
|
||||
### 12. Netutil package contains functions to get net information and send http request.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/netutil"
|
||||
@@ -293,11 +324,14 @@ import "github.com/duke-git/lancet/v2/netutil"
|
||||
|
||||
#### Function list:
|
||||
- [ConvertMapToQueryString](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ConvertMapToQueryString)
|
||||
- [EncodeUrl](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#EncodeUrl)
|
||||
- [GetInternalIp](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetInternalIp)
|
||||
- [GetIps](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetIps)
|
||||
- [GetMacAddrs](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetMacAddrs)
|
||||
- [GetPublicIpInfo](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetPublicIpInfo)
|
||||
- [GetRequestPublicIp](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetRequestPublicIp)
|
||||
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsPublicIP)
|
||||
- [IsInternalIP](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsInternalIP)
|
||||
- [HttpGet](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet)
|
||||
- [HttpDelete](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete)
|
||||
- [HttpPost](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost)
|
||||
@@ -305,7 +339,7 @@ import "github.com/duke-git/lancet/v2/netutil"
|
||||
- [HttpPatch](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPatch)
|
||||
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse)
|
||||
|
||||
### 12. Random package implements some basic functions to generate random int and string.
|
||||
### 13. Random package implements some basic functions to generate random int and string.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/random"
|
||||
@@ -317,7 +351,7 @@ import "github.com/duke-git/lancet/v2/random"
|
||||
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandString)
|
||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
|
||||
|
||||
### 13. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
|
||||
### 14. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/retry"
|
||||
@@ -330,7 +364,7 @@ import "github.com/duke-git/lancet/v2/retry"
|
||||
- [RetryDuration](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryDuration)
|
||||
- [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryTimes)
|
||||
|
||||
### 14. Slice contains some functions to manipulate slice.
|
||||
### 15. Slice contains some functions to manipulate slice.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/slice"
|
||||
@@ -348,11 +382,14 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- [DifferenceWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)
|
||||
- [DeleteAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteAt)
|
||||
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)
|
||||
- [Equal](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Equal)
|
||||
- [EqualWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#EqualWith)
|
||||
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Every)
|
||||
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)
|
||||
- [Find](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Find)
|
||||
- [FindLast](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLast)
|
||||
- [FlattenDeep](#FlattenDeep)
|
||||
- [Flatten](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Flatten)
|
||||
- [FlattenDeep](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlattenDeep)
|
||||
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)
|
||||
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupBy)
|
||||
- [GroupWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupWith)
|
||||
@@ -370,12 +407,15 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Some)
|
||||
- [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#StringSlice)
|
||||
- [SymmetricDifference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SymmetricDifference)
|
||||
- [ToSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ToSlice)
|
||||
- [ToSlicePointer](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ToSlicePointer)
|
||||
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Unique)
|
||||
- [UniqueBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UniqueBy)
|
||||
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Union)
|
||||
- [UpdateAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UpdateAt)
|
||||
- [Without](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Without)
|
||||
|
||||
### 15. Strutil package contains some functions to manipulate string.
|
||||
### 16. Strutil package contains some functions to manipulate string.
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/strutil"
|
||||
```
|
||||
@@ -400,7 +440,7 @@ import "github.com/duke-git/lancet/v2/strutil"
|
||||
- [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Wrap)
|
||||
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap)
|
||||
|
||||
### 16. System package contain some functions about os, runtime, shell command.
|
||||
### 17. System package contain some functions about os, runtime, shell command.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/system"
|
||||
@@ -414,8 +454,9 @@ import "github.com/duke-git/lancet/v2/system"
|
||||
- [RemoveOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#RemoveOsEnv)
|
||||
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#CompareOsEnv)
|
||||
- [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system.md#ExecCommand)
|
||||
- [GetOsBits](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsBits)
|
||||
|
||||
### 17. Validator package contains some functions for data validation.
|
||||
### 18. Validator package contains some functions for data validation.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/validator"
|
||||
@@ -449,7 +490,7 @@ import "github.com/duke-git/lancet/v2/validator"
|
||||
- [IsStrongPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsStrongPassword)
|
||||
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsUrl)
|
||||
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsWeakPassword)
|
||||
### 18. xerror package implements helpers for errors.
|
||||
### 19. xerror package implements helpers for errors.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/xerror"
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
<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://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
@@ -35,9 +35,9 @@
|
||||
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
|
||||
```
|
||||
|
||||
2. <b>使用go1.18以下版本的用户,必须安装v1.x.x。目前最新的v1版本是v1.2.9。</b>
|
||||
2. <b>使用go1.18以下版本的用户,必须安装v1.x.x。目前最新的v1版本是v1.3.0。</b>
|
||||
```go
|
||||
go get github.com/duke-git/lancet@v1.2.9 // 使用go1.18以下版本, 必须安装v1.x.x版本
|
||||
go get github.com/duke-git/lancet@v1.3.0 // 使用go1.18以下版本, 必须安装v1.x.x版本
|
||||
```
|
||||
|
||||
## 用法
|
||||
@@ -117,11 +117,15 @@ import "github.com/duke-git/lancet/v2/convertor"
|
||||
- [ToBool](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToBool)
|
||||
- [ToBytes](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToBytes)
|
||||
- [ToChar](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToChar)
|
||||
- [ToChannel](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToChannel)
|
||||
- [ToFloat](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToFloat)
|
||||
- [ToInt](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToInt)
|
||||
- [ToJson](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToJson)
|
||||
- [ToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToMap)
|
||||
- [ToPointer](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToPointer)
|
||||
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToString)
|
||||
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#StructToMap)
|
||||
|
||||
- [MapToSlice](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#MapToSlice)
|
||||
### 4. cryptor加密包支持数据加密和解密,获取md5,hash值。支持base64, md5, hmac, aes, des, rsa。
|
||||
|
||||
```go
|
||||
@@ -200,7 +204,30 @@ import "github.com/duke-git/lancet/v2/datetime"
|
||||
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormatForTpl)
|
||||
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)
|
||||
|
||||
### 6. fileutil包支持文件基本操作。
|
||||
|
||||
### 6. datastructure包含一些普通的数据结构实现。例如:list, linklist, stack, queue, set, tree, graph.
|
||||
|
||||
|
||||
```go
|
||||
import list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
import link "github.com/duke-git/lancet/v2/datastructure/link"
|
||||
import stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
import queue "github.com/duke-git/lancet/v2/datastructure/queue"
|
||||
import set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
import tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
import heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
```
|
||||
#### Function list:
|
||||
- [List](https://github.com/duke-git/lancet/blob/main/docs/datastructure/list_zh-CN.md)
|
||||
- [Linklist](https://github.com/duke-git/lancet/blob/main/docs/datastructure/linklist_zh-CN.md)
|
||||
- [Stack](https://github.com/duke-git/lancet/blob/main/docs/datastructure/stack_zh-CN.md)
|
||||
- [Queue](https://github.com/duke-git/lancet/blob/main/docs/datastructure/queue_zh-CN.md)
|
||||
- [Set](https://github.com/duke-git/lancet/blob/main/docs/datastructure/set_zh-CN.md)
|
||||
- [Tree](https://github.com/duke-git/lancet/blob/main/docs/datastructure/tree_zh-CN.md)
|
||||
- [Heap](https://github.com/duke-git/lancet/blob/main/docs/datastructure/heap.md)
|
||||
|
||||
|
||||
### 7. fileutil包支持文件基本操作。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/fileutil"
|
||||
@@ -210,6 +237,7 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
|
||||
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ClearFile)
|
||||
- [CreateFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CreateFile)
|
||||
- [CreateDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CreateDir)
|
||||
- [CopyFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CopyFile)
|
||||
- [FileMode](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#FileMode)
|
||||
- [MiMeType](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#MiMeType)
|
||||
@@ -223,7 +251,7 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Zip)
|
||||
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)
|
||||
|
||||
### 7. formatter格式化器包含一些数据格式化处理方法。
|
||||
### 8. formatter格式化器包含一些数据格式化处理方法。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/formatter"
|
||||
@@ -232,7 +260,7 @@ import "github.com/duke-git/lancet/v2/formatter"
|
||||
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Comma)
|
||||
|
||||
|
||||
### 8. function函数包控制函数执行流程,包含部分函数式编程。
|
||||
### 9. function函数包控制函数执行流程,包含部分函数式编程。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/function"
|
||||
@@ -248,7 +276,7 @@ import "github.com/duke-git/lancet/v2/function"
|
||||
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)
|
||||
|
||||
|
||||
### 9. maputil包包括一些操作map的函数.
|
||||
### 10. maputil包包括一些操作map的函数.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/maputil"
|
||||
@@ -262,8 +290,9 @@ import "github.com/duke-git/lancet/v2/maputil"
|
||||
- [Merge](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Merge)
|
||||
- [Minus](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Minus)
|
||||
- [Values](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Values)
|
||||
- [IsDisjoint](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#IsDisjoint)
|
||||
|
||||
### 10. mathutil包实现了一些数学计算的函数。
|
||||
### 11. mathutil包实现了一些数学计算的函数。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/mathutil"
|
||||
@@ -283,7 +312,7 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
||||
- [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToString)
|
||||
- [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#TruncRound)
|
||||
|
||||
### 11. netutil网络包支持获取ip地址,发送http请求。
|
||||
### 12. netutil网络包支持获取ip地址,发送http请求。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/netutil"
|
||||
@@ -292,10 +321,13 @@ import "github.com/duke-git/lancet/v2/netutil"
|
||||
#### 函数列表:
|
||||
- [ConvertMapToQueryString](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ConvertMapToQueryString)
|
||||
- [GetInternalIp](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetInternalIp)
|
||||
- [EncodeUrl](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#EncodeUrl)
|
||||
- [GetIps](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetIps)
|
||||
- [GetMacAddrs](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetMacAddrs)
|
||||
- [GetPublicIpInfo](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetPublicIpInfo)
|
||||
- [GetRequestPublicIp](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetRequestPublicIp)
|
||||
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsPublicIP)
|
||||
- [IsInternalIP](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsInternalIP)
|
||||
- [HttpGet](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpGet)
|
||||
- [HttpDelete](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpDelete)
|
||||
- [HttpPost](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPost)
|
||||
@@ -303,7 +335,7 @@ import "github.com/duke-git/lancet/v2/netutil"
|
||||
- [HttpPatch](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch)
|
||||
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse)
|
||||
|
||||
### 12. random随机数生成器包,可以生成随机[]bytes, int, string。
|
||||
### 13. random随机数生成器包,可以生成随机[]bytes, int, string。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/random"
|
||||
@@ -314,7 +346,7 @@ import "github.com/duke-git/lancet/v2/random"
|
||||
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandInt)
|
||||
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandString)
|
||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
|
||||
### 13. retry重试执行函数直到函数运行成功或被context cancel。
|
||||
### 14. retry重试执行函数直到函数运行成功或被context cancel。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/retry"
|
||||
@@ -328,7 +360,7 @@ import "github.com/duke-git/lancet/v2/retry"
|
||||
- [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes)
|
||||
|
||||
|
||||
### 14. slice包包含操作切片的方法集合。
|
||||
### 15. slice包包含操作切片的方法集合。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/slice"
|
||||
@@ -350,7 +382,8 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Filter)
|
||||
- [Find](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Find)
|
||||
- [FindLast](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindLast)
|
||||
- [FlattenDeep](#FlattenDeep)
|
||||
- [Flatten](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Flatten)
|
||||
- [FlattenDeep](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FlattenDeep)
|
||||
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ForEach)
|
||||
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupBy)
|
||||
- [GroupWith](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupWith)
|
||||
@@ -368,13 +401,16 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Some)
|
||||
- [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#StringSlice)
|
||||
- [SymmetricDifference](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SymmetricDifference)
|
||||
- [ToSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ToSlice)
|
||||
- [ToSlicePointer](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ToSlicePointer)
|
||||
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Unique)
|
||||
- [UniqueBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UniqueBy)
|
||||
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Union)
|
||||
- [UpdateAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UpdateAt)
|
||||
- [Without](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Without)
|
||||
|
||||
|
||||
### 15. strutil包含处理字符串的相关函数。
|
||||
### 16. strutil包含处理字符串的相关函数。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/strutil"
|
||||
@@ -401,7 +437,7 @@ import "github.com/duke-git/lancet/v2/strutil"
|
||||
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap)
|
||||
|
||||
|
||||
### 16. system包含os, runtime, shell command相关函数。
|
||||
### 17. system包含os, runtime, shell command相关函数。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/system"
|
||||
@@ -416,8 +452,9 @@ import "github.com/duke-git/lancet/v2/system"
|
||||
- [RemoveOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#RemoveOsEnv)
|
||||
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#CompareOsEnv)
|
||||
- [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#ExecCommand)
|
||||
- [GetOsBits](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#GetOsBits)
|
||||
|
||||
### 17. validator验证器包,包含常用字符串格式验证函数。
|
||||
### 18. validator验证器包,包含常用字符串格式验证函数。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/validator"
|
||||
@@ -452,7 +489,7 @@ import "github.com/duke-git/lancet/v2/validator"
|
||||
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsWeakPassword)
|
||||
|
||||
validator.md#IsWeakPassword)
|
||||
### 18. xerror包实现一些错误处理函数
|
||||
### 19. xerror包实现一些错误处理函数
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/xerror"
|
||||
|
||||
@@ -74,72 +74,86 @@ func ToChar(s string) []string {
|
||||
return c
|
||||
}
|
||||
|
||||
// ToChannel convert a array of elements to a read-only channels
|
||||
func ToChannel[T any](array []T) <-chan T {
|
||||
ch := make(chan T)
|
||||
|
||||
go func() {
|
||||
for _, item := range array {
|
||||
ch <- item
|
||||
}
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
// ToString convert value to string
|
||||
func ToString(value any) string {
|
||||
res := ""
|
||||
result := ""
|
||||
if value == nil {
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
switch value.(type) {
|
||||
case float32, float64:
|
||||
res = strconv.FormatFloat(v.Float(), 'f', -1, 64)
|
||||
return res
|
||||
result = strconv.FormatFloat(v.Float(), 'f', -1, 64)
|
||||
return result
|
||||
case int, int8, int16, int32, int64:
|
||||
res = strconv.FormatInt(v.Int(), 10)
|
||||
return res
|
||||
result = strconv.FormatInt(v.Int(), 10)
|
||||
return result
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
res = strconv.FormatUint(v.Uint(), 10)
|
||||
return res
|
||||
result = strconv.FormatUint(v.Uint(), 10)
|
||||
return result
|
||||
case string:
|
||||
res = v.String()
|
||||
return res
|
||||
result = v.String()
|
||||
return result
|
||||
case []byte:
|
||||
res = string(v.Bytes())
|
||||
return res
|
||||
result = string(v.Bytes())
|
||||
return result
|
||||
default:
|
||||
newValue, _ := json.Marshal(value)
|
||||
res = string(newValue)
|
||||
return res
|
||||
result = string(newValue)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// ToJson convert value to a valid json string
|
||||
func ToJson(value any) (string, error) {
|
||||
res, err := json.Marshal(value)
|
||||
result, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(res), nil
|
||||
return string(result), nil
|
||||
}
|
||||
|
||||
// ToFloat convert value to a float64, if input is not a float return 0.0 and error
|
||||
func ToFloat(value any) (float64, error) {
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
res := 0.0
|
||||
result := 0.0
|
||||
err := fmt.Errorf("ToInt: unvalid interface type %T", value)
|
||||
switch value.(type) {
|
||||
case int, int8, int16, int32, int64:
|
||||
res = float64(v.Int())
|
||||
return res, nil
|
||||
result = float64(v.Int())
|
||||
return result, nil
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
res = float64(v.Uint())
|
||||
return res, nil
|
||||
result = float64(v.Uint())
|
||||
return result, nil
|
||||
case float32, float64:
|
||||
res = v.Float()
|
||||
return res, nil
|
||||
result = v.Float()
|
||||
return result, nil
|
||||
case string:
|
||||
res, err = strconv.ParseFloat(v.String(), 64)
|
||||
result, err = strconv.ParseFloat(v.String(), 64)
|
||||
if err != nil {
|
||||
res = 0.0
|
||||
result = 0.0
|
||||
}
|
||||
return res, err
|
||||
return result, err
|
||||
default:
|
||||
return res, err
|
||||
return result, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,29 +161,45 @@ func ToFloat(value any) (float64, error) {
|
||||
func ToInt(value any) (int64, error) {
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
var res int64
|
||||
var result int64
|
||||
err := fmt.Errorf("ToInt: invalid interface type %T", value)
|
||||
switch value.(type) {
|
||||
case int, int8, int16, int32, int64:
|
||||
res = v.Int()
|
||||
return res, nil
|
||||
result = v.Int()
|
||||
return result, nil
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
res = int64(v.Uint())
|
||||
return res, nil
|
||||
result = int64(v.Uint())
|
||||
return result, nil
|
||||
case float32, float64:
|
||||
res = int64(v.Float())
|
||||
return res, nil
|
||||
result = int64(v.Float())
|
||||
return result, nil
|
||||
case string:
|
||||
res, err = strconv.ParseInt(v.String(), 0, 64)
|
||||
result, err = strconv.ParseInt(v.String(), 0, 64)
|
||||
if err != nil {
|
||||
res = 0
|
||||
result = 0
|
||||
}
|
||||
return res, err
|
||||
return result, err
|
||||
default:
|
||||
return res, err
|
||||
return result, err
|
||||
}
|
||||
}
|
||||
|
||||
// ToPointer returns a pointer to this value
|
||||
func ToPointer[T any](value T) *T {
|
||||
return &value
|
||||
}
|
||||
|
||||
// ToMap convert a slice or an array of structs to a map based on iteratee function
|
||||
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V {
|
||||
result := make(map[K]V, len(array))
|
||||
for _, item := range array {
|
||||
k, v := iteratee(item)
|
||||
result[k] = v
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// StructToMap convert struct to map, only convert exported struct field
|
||||
// map key is specified same as struct field tag `json` value
|
||||
func StructToMap(value any) (map[string]any, error) {
|
||||
@@ -183,7 +213,7 @@ func StructToMap(value any) (map[string]any, error) {
|
||||
return nil, fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", value)
|
||||
}
|
||||
|
||||
res := make(map[string]any)
|
||||
result := make(map[string]any)
|
||||
|
||||
fieldNum := t.NumField()
|
||||
pattern := `^[A-Z]`
|
||||
@@ -192,12 +222,23 @@ func StructToMap(value any) (map[string]any, error) {
|
||||
name := t.Field(i).Name
|
||||
tag := t.Field(i).Tag.Get("json")
|
||||
if regex.MatchString(name) && tag != "" {
|
||||
//res[name] = v.Field(i).Interface()
|
||||
res[tag] = v.Field(i).Interface()
|
||||
//result[name] = v.Field(i).Interface()
|
||||
result[tag] = v.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// MapToSlice convert a map to a slice based on iteratee function
|
||||
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T {
|
||||
result := make([]T, 0, len(aMap))
|
||||
|
||||
for k, v := range aMap {
|
||||
result = append(result, iteratee(k, v))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// ColorHexToRGB convert hex color to rgb color
|
||||
|
||||
@@ -2,6 +2,7 @@ package convertor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
@@ -21,6 +22,23 @@ func TestToChar(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestToChannel(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToChannel")
|
||||
|
||||
ch := ToChannel([]int{1, 2, 3})
|
||||
val1, _ := <-ch
|
||||
assert.Equal(1, val1)
|
||||
|
||||
val2, _ := <-ch
|
||||
assert.Equal(2, val2)
|
||||
|
||||
val3, _ := <-ch
|
||||
assert.Equal(3, val3)
|
||||
|
||||
_, ok := <-ch
|
||||
assert.Equal(false, ok)
|
||||
}
|
||||
|
||||
func TestToBool(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToBool")
|
||||
|
||||
@@ -142,6 +160,25 @@ func TestToJson(t *testing.T) {
|
||||
assert.Equal("{\"Name\":\"TestStruct\"}", structJsonStr)
|
||||
}
|
||||
|
||||
func TestToMap(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToMap")
|
||||
|
||||
type Message struct {
|
||||
name string
|
||||
code int
|
||||
}
|
||||
messages := []Message{
|
||||
{name: "Hello", code: 100},
|
||||
{name: "Hi", code: 101},
|
||||
}
|
||||
result := ToMap(messages, func(msg Message) (int, string) {
|
||||
return msg.code, msg.name
|
||||
})
|
||||
expected := map[int]string{100: "Hello", 101: "Hi"}
|
||||
|
||||
assert.Equal(expected, result)
|
||||
}
|
||||
|
||||
func TestStructToMap(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStructToMap")
|
||||
|
||||
@@ -154,10 +191,22 @@ func TestStructToMap(t *testing.T) {
|
||||
100,
|
||||
}
|
||||
pm, _ := StructToMap(p)
|
||||
var expected = map[string]any{"name": "test"}
|
||||
|
||||
expected := map[string]any{"name": "test"}
|
||||
assert.Equal(expected, pm)
|
||||
}
|
||||
|
||||
func TestMapToSlice(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMapToSlice")
|
||||
|
||||
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
result := MapToSlice(aMap, func(key string, value int) string {
|
||||
return key + ":" + strconv.Itoa(value)
|
||||
})
|
||||
|
||||
assert.Equal([]string{"a:1", "b:2", "c:3"}, result)
|
||||
}
|
||||
|
||||
func TestColorHexToRGB(t *testing.T) {
|
||||
colorHex := "#003366"
|
||||
r, g, b := ColorHexToRGB(colorHex)
|
||||
@@ -178,3 +227,10 @@ func TestColorRGBToHex(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestColorRGBToHex")
|
||||
assert.Equal(expected, colorHex)
|
||||
}
|
||||
|
||||
func TestToPointer(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToPointer")
|
||||
result := ToPointer(123)
|
||||
|
||||
assert.Equal(*result, 123)
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func AesEcbEncrypt(data, key []byte) []byte {
|
||||
func AesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
cipher, _ := aes.NewCipher(generateAesKey(key))
|
||||
decrypted := make([]byte, len(encrypted))
|
||||
//
|
||||
|
||||
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||||
}
|
||||
@@ -54,14 +54,18 @@ func AesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
// AesCbcEncrypt encrypt data with key use AES CBC algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesCbcEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 16, 24 or 32
|
||||
block, _ := aes.NewCipher(key)
|
||||
blockSize := block.BlockSize()
|
||||
data = pkcs7Padding(data, blockSize)
|
||||
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
|
||||
data = pkcs7Padding(data, block.BlockSize())
|
||||
|
||||
encrypted := make([]byte, aes.BlockSize+len(data))
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted[aes.BlockSize:], data)
|
||||
|
||||
encrypted := make([]byte, len(data))
|
||||
blockMode.CryptBlocks(encrypted, data)
|
||||
return encrypted
|
||||
}
|
||||
|
||||
@@ -69,12 +73,14 @@ func AesCbcEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
block, _ := aes.NewCipher(key)
|
||||
blockSize := block.BlockSize()
|
||||
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
|
||||
|
||||
decrypted := make([]byte, len(encrypted))
|
||||
blockMode.CryptBlocks(decrypted, encrypted)
|
||||
decrypted = pkcs7UnPadding(decrypted)
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
encrypted = encrypted[aes.BlockSize:]
|
||||
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted, encrypted)
|
||||
|
||||
decrypted := pkcs7UnPadding(encrypted)
|
||||
return decrypted
|
||||
}
|
||||
|
||||
|
||||
@@ -55,12 +55,16 @@ func DesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
// len(key) should be 8
|
||||
func DesCbcEncrypt(data, key []byte) []byte {
|
||||
block, _ := des.NewCipher(key)
|
||||
blockSize := block.BlockSize()
|
||||
data = pkcs7Padding(data, blockSize)
|
||||
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
|
||||
data = pkcs7Padding(data, block.BlockSize())
|
||||
|
||||
encrypted := make([]byte, len(data))
|
||||
blockMode.CryptBlocks(encrypted, data)
|
||||
encrypted := make([]byte, des.BlockSize+len(data))
|
||||
iv := encrypted[:des.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted[des.BlockSize:], data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
@@ -69,13 +73,14 @@ func DesCbcEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 8
|
||||
func DesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
block, _ := des.NewCipher(key)
|
||||
blockSize := block.BlockSize()
|
||||
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
|
||||
|
||||
decrypted := make([]byte, len(encrypted))
|
||||
blockMode.CryptBlocks(decrypted, encrypted)
|
||||
decrypted = pkcs7UnPadding(decrypted)
|
||||
iv := encrypted[:des.BlockSize]
|
||||
encrypted = encrypted[des.BlockSize:]
|
||||
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted, encrypted)
|
||||
|
||||
decrypted := pkcs7UnPadding(encrypted)
|
||||
return decrypted
|
||||
}
|
||||
|
||||
|
||||
189
datastructure/heap/maxheap.go
Normal file
189
datastructure/heap/maxheap.go
Normal file
@@ -0,0 +1,189 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/duke-git/lancet/v2/lancetconstraints"
|
||||
)
|
||||
|
||||
// MaxHeap implements a binary max heap
|
||||
// type T should implements Compare function in lancetconstraints.Comparator interface.
|
||||
type MaxHeap[T any] struct {
|
||||
data []T
|
||||
comparator lancetconstraints.Comparator
|
||||
}
|
||||
|
||||
// NewMaxHeap returns a MaxHeap instance with the given comparator.
|
||||
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T] {
|
||||
return &MaxHeap[T]{
|
||||
data: make([]T, 0),
|
||||
comparator: comparator,
|
||||
}
|
||||
}
|
||||
|
||||
// Push value into the heap
|
||||
func (h *MaxHeap[T]) Push(value T) {
|
||||
h.data = append(h.data, value)
|
||||
h.heapifyUp(len(h.data) - 1)
|
||||
}
|
||||
|
||||
// heapifyUp heapify the data from bottom to top
|
||||
func (h *MaxHeap[T]) heapifyUp(i int) {
|
||||
for h.comparator.Compare(h.data[parentIndex(i)], h.data[i]) < 0 {
|
||||
h.swap(parentIndex(i), i)
|
||||
i = parentIndex(i)
|
||||
}
|
||||
}
|
||||
|
||||
// Pop return the largest value, and remove it from the heap
|
||||
// if heap is empty, return zero value and fasle
|
||||
func (h *MaxHeap[T]) Pop() (T, bool) {
|
||||
var val T
|
||||
if h.Size() == 0 {
|
||||
return val, false
|
||||
}
|
||||
|
||||
val = h.data[0]
|
||||
l := len(h.data) - 1
|
||||
|
||||
h.data[0] = h.data[l]
|
||||
h.data = h.data[:l]
|
||||
h.heapifyDown(0)
|
||||
|
||||
return val, true
|
||||
}
|
||||
|
||||
// heapifyDown heapify the data from top to bottom
|
||||
func (h *MaxHeap[T]) heapifyDown(i int) {
|
||||
lastIndex := len(h.data) - 1
|
||||
l, r := leftChildIndex(i), rightChildIndex(i)
|
||||
childToCompare := 0
|
||||
|
||||
for l <= lastIndex {
|
||||
if l == lastIndex {
|
||||
childToCompare = l
|
||||
} else if h.comparator.Compare(h.data[l], h.data[r]) > 0 {
|
||||
childToCompare = l
|
||||
} else {
|
||||
childToCompare = r
|
||||
}
|
||||
|
||||
if h.comparator.Compare(h.data[i], h.data[childToCompare]) < 0 {
|
||||
h.swap(i, childToCompare)
|
||||
i = childToCompare
|
||||
l, r = leftChildIndex(i), rightChildIndex(i)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Peek returns the largest element from the heap without removing it.
|
||||
// if heap is empty, it returns zero value and false.
|
||||
func (h *MaxHeap[T]) Peek() (T, bool) {
|
||||
if h.Size() == 0 {
|
||||
var val T
|
||||
return val, false
|
||||
}
|
||||
|
||||
return h.data[0], true
|
||||
}
|
||||
|
||||
// Size return the number of elements in the heap
|
||||
func (h *MaxHeap[T]) Size() int {
|
||||
return len(h.data)
|
||||
}
|
||||
|
||||
// Data return data of the heap
|
||||
func (h *MaxHeap[T]) Data() []T {
|
||||
return h.data
|
||||
}
|
||||
|
||||
// PrintStructure print the structure of the heap
|
||||
func (h *MaxHeap[T]) PrintStructure() {
|
||||
level := 1
|
||||
data := h.data
|
||||
length := len(h.data)
|
||||
index := 0
|
||||
|
||||
list := [][]string{}
|
||||
temp := []string{}
|
||||
for index < length {
|
||||
start := powerTwo(level-1) - 1
|
||||
end := start + powerTwo(level-1) - 1
|
||||
|
||||
temp = append(temp, fmt.Sprintf("%v", data[index]))
|
||||
index++
|
||||
|
||||
if index > end || index >= length {
|
||||
list = append(list, temp)
|
||||
temp = []string{}
|
||||
|
||||
if index < length {
|
||||
level++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastNum := powerTwo(level - 1)
|
||||
lastLen := lastNum + (lastNum - 1)
|
||||
|
||||
heapTree := make([][]string, level, level)
|
||||
for i := 0; i < level; i++ {
|
||||
heapTree[i] = make([]string, lastLen, lastLen)
|
||||
for j := 0; j < lastLen; j++ {
|
||||
heapTree[i][j] = ""
|
||||
}
|
||||
}
|
||||
|
||||
for k := 0; k < len(list); k++ {
|
||||
vals := list[k]
|
||||
tempLevel := level - k
|
||||
st := powerTwo(tempLevel-1) - 1
|
||||
for _, v := range vals {
|
||||
heapTree[k][st] = v
|
||||
gap := powerTwo(tempLevel)
|
||||
st = st + gap
|
||||
}
|
||||
}
|
||||
|
||||
for m := 0; m < level; m++ {
|
||||
for n := 0; n < lastLen; n++ {
|
||||
val := heapTree[m][n]
|
||||
if val == "" {
|
||||
fmt.Printf(" ")
|
||||
} else {
|
||||
fmt.Printf(val)
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
// parentIndex get parent index of the given index
|
||||
func parentIndex(i int) int {
|
||||
return (i - 1) / 2
|
||||
}
|
||||
|
||||
// leftChildIndex get left child index of the given index
|
||||
func leftChildIndex(i int) int {
|
||||
return 2*i + 1
|
||||
}
|
||||
|
||||
// rightChildIndex get right child index of the given index
|
||||
func rightChildIndex(i int) int {
|
||||
return 2*i + 2
|
||||
}
|
||||
|
||||
// swap two elements in the heap
|
||||
func (h *MaxHeap[T]) swap(i, j int) {
|
||||
h.data[i], h.data[j] = h.data[j], h.data[i]
|
||||
}
|
||||
|
||||
func powerTwo(n int) int {
|
||||
return 1 << n
|
||||
}
|
||||
78
datastructure/heap/maxheap_test.go
Normal file
78
datastructure/heap/maxheap_test.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func TestMaxHeap_Push(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMaxHeap_Push")
|
||||
|
||||
heap := NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
heap.Push(v)
|
||||
}
|
||||
|
||||
expected := []int{12, 9, 11, 4, 8, 10, 7, 1, 3, 5, 6, 2}
|
||||
assert.Equal(expected, heap.data)
|
||||
|
||||
assert.Equal(12, heap.Size())
|
||||
|
||||
heap.PrintStructure()
|
||||
}
|
||||
|
||||
func TestMaxHeap_Pop(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMaxHeap_Pop")
|
||||
|
||||
heap := NewMaxHeap[int](&intComparator{})
|
||||
|
||||
_, ok := heap.Pop()
|
||||
assert.Equal(false, ok)
|
||||
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
for _, v := range values {
|
||||
heap.Push(v)
|
||||
}
|
||||
|
||||
val, ok := heap.Pop()
|
||||
assert.Equal(12, val)
|
||||
assert.Equal(true, ok)
|
||||
assert.Equal(11, heap.Size())
|
||||
}
|
||||
|
||||
func TestMaxHeap_Peek(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMaxHeap_Peek")
|
||||
|
||||
heap := NewMaxHeap[int](&intComparator{})
|
||||
|
||||
_, ok := heap.Peek()
|
||||
assert.Equal(false, ok)
|
||||
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
for _, v := range values {
|
||||
heap.Push(v)
|
||||
}
|
||||
|
||||
val, ok := heap.Peek()
|
||||
assert.Equal(12, val)
|
||||
assert.Equal(true, ok)
|
||||
|
||||
assert.Equal(12, heap.Size())
|
||||
}
|
||||
@@ -208,13 +208,13 @@ func (link *DoublyLink[T]) Size() int {
|
||||
|
||||
// Values return slice of all doubly linklist node value
|
||||
func (link *DoublyLink[T]) Values() []T {
|
||||
res := []T{}
|
||||
result := []T{}
|
||||
current := link.Head
|
||||
for current != nil {
|
||||
res = append(res, current.Value)
|
||||
result = append(result, current.Value)
|
||||
current = current.Next
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Print all nodes info of a linked list
|
||||
@@ -234,7 +234,7 @@ func (link *DoublyLink[T]) IsEmpty() bool {
|
||||
return link.length == 0
|
||||
}
|
||||
|
||||
// Clear checks if link is empty or not
|
||||
// Clear all nodes in doubly linklist
|
||||
func (link *DoublyLink[T]) Clear() {
|
||||
link.Head = nil
|
||||
link.length = 0
|
||||
|
||||
@@ -213,13 +213,13 @@ func (link *SinglyLink[T]) Size() int {
|
||||
|
||||
// Values return slice of all singly linklist node value
|
||||
func (link *SinglyLink[T]) Values() []T {
|
||||
res := []T{}
|
||||
result := []T{}
|
||||
current := link.Head
|
||||
for current != nil {
|
||||
res = append(res, current.Value)
|
||||
result = append(result, current.Value)
|
||||
current = current.Next
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// IsEmpty checks if link is empty or not
|
||||
@@ -227,7 +227,7 @@ func (link *SinglyLink[T]) IsEmpty() bool {
|
||||
return link.length == 0
|
||||
}
|
||||
|
||||
// Clear checks if link is empty or not
|
||||
// Clear all the node in singly linklist
|
||||
func (link *SinglyLink[T]) Clear() {
|
||||
link.Head = nil
|
||||
link.length = 0
|
||||
|
||||
@@ -132,8 +132,8 @@ func (l *List[T]) UpdateAt(index int, value T) {
|
||||
l.data = append(data[:index], append([]T{value}, data[index+1:]...)...)
|
||||
}
|
||||
|
||||
// Equtal compare list to other list, use reflect.DeepEqual
|
||||
func (l *List[T]) Equtal(other *List[T]) bool {
|
||||
// Equal compare list to other list, use reflect.DeepEqual
|
||||
func (l *List[T]) Equal(other *List[T]) bool {
|
||||
if len(l.data) != len(other.data) {
|
||||
return false
|
||||
}
|
||||
@@ -222,24 +222,24 @@ func (l *List[T]) Unique() {
|
||||
|
||||
// Union creates a new list contain all element in list l and other, remove duplicate element.
|
||||
func (l *List[T]) Union(other *List[T]) *List[T] {
|
||||
res := NewList([]T{})
|
||||
result := NewList([]T{})
|
||||
|
||||
res.data = append(res.data, l.data...)
|
||||
res.data = append(res.data, other.data...)
|
||||
res.Unique()
|
||||
result.data = append(result.data, l.data...)
|
||||
result.data = append(result.data, other.data...)
|
||||
result.Unique()
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Intersection creates a new list whose element both be contained in list l and other
|
||||
func (l *List[T]) Intersection(other *List[T]) *List[T] {
|
||||
res := NewList(make([]T, 0, 0))
|
||||
result := NewList(make([]T, 0, 0))
|
||||
|
||||
for _, v := range l.data {
|
||||
if other.Contain(v) {
|
||||
res.data = append(res.data, v)
|
||||
result.data = append(result.data, v)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -155,15 +155,15 @@ func TestUpdateAt(t *testing.T) {
|
||||
assert.Equal([]int{5, 2, 3, 1}, list.Data())
|
||||
}
|
||||
|
||||
func TestEqutal(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEqutal")
|
||||
func TestEqual(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEqual")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
list2 := NewList([]int{1, 2, 3, 4})
|
||||
list3 := NewList([]int{1, 2, 3})
|
||||
|
||||
assert.Equal(true, list1.Equtal(list2))
|
||||
assert.Equal(false, list1.Equtal(list3))
|
||||
assert.Equal(true, list1.Equal(list2))
|
||||
assert.Equal(false, list1.Equal(list3))
|
||||
}
|
||||
|
||||
func TestIsEmpty(t *testing.T) {
|
||||
@@ -192,7 +192,7 @@ func TestClone(t *testing.T) {
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
list2 := list1.Clone()
|
||||
|
||||
assert.Equal(true, list1.Equtal(list2))
|
||||
assert.Equal(true, list1.Equal(list2))
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
@@ -203,7 +203,7 @@ func TestMerge(t *testing.T) {
|
||||
expected := NewList([]int{1, 2, 3, 4, 4, 5, 6})
|
||||
|
||||
list3 := list1.Merge(list2)
|
||||
assert.Equal(true, expected.Equtal(list3))
|
||||
assert.Equal(true, expected.Equal(list3))
|
||||
}
|
||||
|
||||
func TestSize(t *testing.T) {
|
||||
@@ -224,7 +224,7 @@ func TestSwap(t *testing.T) {
|
||||
|
||||
list.Swap(0, 3)
|
||||
|
||||
assert.Equal(true, expected.Equtal(list))
|
||||
assert.Equal(true, expected.Equal(list))
|
||||
}
|
||||
|
||||
func TestReverse(t *testing.T) {
|
||||
@@ -235,7 +235,7 @@ func TestReverse(t *testing.T) {
|
||||
|
||||
list.Reverse()
|
||||
|
||||
assert.Equal(true, expected.Equtal(list))
|
||||
assert.Equal(true, expected.Equal(list))
|
||||
}
|
||||
|
||||
func TestUnique(t *testing.T) {
|
||||
@@ -246,7 +246,7 @@ func TestUnique(t *testing.T) {
|
||||
|
||||
list.Unique()
|
||||
|
||||
assert.Equal(true, expected.Equtal(list))
|
||||
assert.Equal(true, expected.Equal(list))
|
||||
}
|
||||
|
||||
func TestUnion(t *testing.T) {
|
||||
@@ -257,7 +257,7 @@ func TestUnion(t *testing.T) {
|
||||
expected := NewList([]int{1, 2, 3, 4, 5, 6})
|
||||
|
||||
list3 := list1.Union(list2)
|
||||
assert.Equal(true, expected.Equtal(list3))
|
||||
assert.Equal(true, expected.Equal(list3))
|
||||
}
|
||||
|
||||
func TestIntersection(t *testing.T) {
|
||||
@@ -268,5 +268,5 @@ func TestIntersection(t *testing.T) {
|
||||
expected := NewList([]int{4})
|
||||
|
||||
list3 := list1.Intersection(list2)
|
||||
assert.Equal(true, expected.Equtal(list3))
|
||||
assert.Equal(true, expected.Equal(list3))
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ func NewArrayQueue[T any](capacity int) *ArrayQueue[T] {
|
||||
}
|
||||
}
|
||||
|
||||
// Data return queue data
|
||||
// Data return slice of queue data
|
||||
func (q *ArrayQueue[T]) Data() []T {
|
||||
items := []T{}
|
||||
for i := q.head; i < q.tail; i++ {
|
||||
@@ -33,7 +33,7 @@ func (q *ArrayQueue[T]) Data() []T {
|
||||
return items
|
||||
}
|
||||
|
||||
// Size return length of queue data
|
||||
// Size return number of elements in queue
|
||||
func (q *ArrayQueue[T]) Size() int {
|
||||
return q.size
|
||||
}
|
||||
@@ -43,6 +43,11 @@ func (q *ArrayQueue[T]) IsEmpty() bool {
|
||||
return q.size == 0
|
||||
}
|
||||
|
||||
// IsFull checks if queue is full or not
|
||||
func (q *ArrayQueue[T]) IsFull() bool {
|
||||
return q.size == q.capacity
|
||||
}
|
||||
|
||||
// Front return front value of queue
|
||||
func (q *ArrayQueue[T]) Front() T {
|
||||
return q.items[0]
|
||||
|
||||
@@ -100,3 +100,14 @@ func TestArrayQueue_Clear(t *testing.T) {
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
assert.Equal(0, queue.Size())
|
||||
}
|
||||
|
||||
func TestArrayQueue_IsFull(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_IsFull")
|
||||
|
||||
queue := NewArrayQueue[int](3)
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
|
||||
assert.Equal(true, queue.IsFull())
|
||||
}
|
||||
|
||||
@@ -7,21 +7,21 @@ import (
|
||||
)
|
||||
|
||||
// CircularQueue implements circular queue with slice,
|
||||
// last index of CircularQueue don't contain value, so acturl capacity is size - 1
|
||||
// last index of CircularQueue don't contain value, so acturl capacity is capacity - 1
|
||||
type CircularQueue[T any] struct {
|
||||
data []T
|
||||
front int
|
||||
rear int
|
||||
size int
|
||||
data []T
|
||||
front int
|
||||
rear int
|
||||
capacity int
|
||||
}
|
||||
|
||||
// NewCircularQueue return a empty CircularQueue pointer
|
||||
func NewCircularQueue[T any](size int) *CircularQueue[T] {
|
||||
data := make([]T, size)
|
||||
return &CircularQueue[T]{data: data, front: 0, rear: 0, size: size}
|
||||
func NewCircularQueue[T any](capacity int) *CircularQueue[T] {
|
||||
data := make([]T, capacity)
|
||||
return &CircularQueue[T]{data: data, front: 0, rear: 0, capacity: capacity}
|
||||
}
|
||||
|
||||
// Data return queue data
|
||||
// Data return slice of queue data
|
||||
func (q *CircularQueue[T]) Data() []T {
|
||||
data := []T{}
|
||||
|
||||
@@ -37,12 +37,12 @@ func (q *CircularQueue[T]) Data() []T {
|
||||
return data
|
||||
}
|
||||
|
||||
// Length return current data length of queue
|
||||
func (q *CircularQueue[T]) Length() int {
|
||||
if q.size == 0 {
|
||||
// Size return number of elements in circular queue
|
||||
func (q *CircularQueue[T]) Size() int {
|
||||
if q.capacity == 0 {
|
||||
return 0
|
||||
}
|
||||
return (q.rear - q.front + q.size) % q.size
|
||||
return (q.rear - q.front + q.capacity) % q.capacity
|
||||
}
|
||||
|
||||
// IsEmpty checks if queue is empty or not
|
||||
@@ -52,7 +52,7 @@ func (q *CircularQueue[T]) IsEmpty() bool {
|
||||
|
||||
// IsFull checks if queue is full or not
|
||||
func (q *CircularQueue[T]) IsFull() bool {
|
||||
return (q.rear+1)%q.size == q.front
|
||||
return (q.rear+1)%q.capacity == q.front
|
||||
}
|
||||
|
||||
// Front return front value of queue
|
||||
@@ -65,23 +65,23 @@ func (q *CircularQueue[T]) Back() T {
|
||||
if q.rear-1 >= 0 {
|
||||
return q.data[q.rear-1]
|
||||
}
|
||||
return q.data[q.size-1]
|
||||
return q.data[q.capacity-1]
|
||||
}
|
||||
|
||||
// EnQueue put element into queue
|
||||
func (q *CircularQueue[T]) EnQueue(value T) error {
|
||||
// Enqueue put element into queue
|
||||
func (q *CircularQueue[T]) Enqueue(value T) error {
|
||||
if q.IsFull() {
|
||||
return errors.New("queue is full!")
|
||||
}
|
||||
|
||||
q.data[q.rear] = value
|
||||
q.rear = (q.rear + 1) % q.size
|
||||
q.rear = (q.rear + 1) % q.capacity
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeQueue remove head element of queue and return it, if queue is empty, return nil and error
|
||||
func (q *CircularQueue[T]) DeQueue() (*T, error) {
|
||||
// Dequeue remove head element of queue and return it, if queue is empty, return nil and error
|
||||
func (q *CircularQueue[T]) Dequeue() (*T, error) {
|
||||
if q.IsEmpty() {
|
||||
return nil, errors.New("queue is empty")
|
||||
}
|
||||
@@ -89,7 +89,7 @@ func (q *CircularQueue[T]) DeQueue() (*T, error) {
|
||||
headItem := q.data[q.front]
|
||||
var t T
|
||||
q.data[q.front] = t
|
||||
q.front = (q.front + 1) % q.size
|
||||
q.front = (q.front + 1) % q.capacity
|
||||
|
||||
return &headItem, nil
|
||||
}
|
||||
@@ -99,7 +99,7 @@ func (q *CircularQueue[T]) Clear() {
|
||||
q.data = []T{}
|
||||
q.front = 0
|
||||
q.rear = 0
|
||||
q.size = 0
|
||||
q.capacity = 0
|
||||
}
|
||||
|
||||
// Contain checks if the value is in queue or not
|
||||
|
||||
@@ -6,47 +6,47 @@ import (
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestCircularQueue_EnQueue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_EnQueue")
|
||||
func TestCircularQueue_Enqueue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Enqueue")
|
||||
|
||||
queue := NewCircularQueue[int](6)
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.EnQueue(4)
|
||||
queue.EnQueue(5)
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
queue.Enqueue(4)
|
||||
queue.Enqueue(5)
|
||||
|
||||
queue.Print()
|
||||
// assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
|
||||
assert.Equal(5, queue.Length())
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
|
||||
assert.Equal(5, queue.Size())
|
||||
|
||||
err := queue.EnQueue(6)
|
||||
err := queue.Enqueue(6)
|
||||
assert.IsNotNil(err)
|
||||
}
|
||||
|
||||
func TestCircularQueue_DeQueue(t *testing.T) {
|
||||
func TestCircularQueue_Dequeue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_DeQueue")
|
||||
|
||||
queue := NewCircularQueue[int](6)
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.EnQueue(4)
|
||||
queue.EnQueue(5)
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
queue.Enqueue(4)
|
||||
queue.Enqueue(5)
|
||||
|
||||
val, err := queue.DeQueue()
|
||||
val, err := queue.Dequeue()
|
||||
assert.IsNil(err)
|
||||
|
||||
assert.Equal(1, *val)
|
||||
assert.Equal(false, queue.IsFull())
|
||||
|
||||
val, _ = queue.DeQueue()
|
||||
val, _ = queue.Dequeue()
|
||||
queue.Print()
|
||||
assert.Equal(2, *val)
|
||||
|
||||
queue.EnQueue(6)
|
||||
queue.Enqueue(6)
|
||||
queue.Print()
|
||||
assert.Equal(false, queue.IsFull())
|
||||
}
|
||||
@@ -55,24 +55,24 @@ func TestCircularQueue_Front(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Front")
|
||||
|
||||
queue := NewCircularQueue[int](6)
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.EnQueue(4)
|
||||
queue.EnQueue(5)
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
queue.Enqueue(4)
|
||||
queue.Enqueue(5)
|
||||
|
||||
queue.Print()
|
||||
|
||||
queue.DeQueue()
|
||||
queue.DeQueue()
|
||||
queue.EnQueue(6)
|
||||
queue.EnQueue(7)
|
||||
queue.Dequeue()
|
||||
queue.Dequeue()
|
||||
queue.Enqueue(6)
|
||||
queue.Enqueue(7)
|
||||
|
||||
queue.Print()
|
||||
|
||||
val := queue.Front()
|
||||
assert.Equal(3, val)
|
||||
assert.Equal(5, queue.Length())
|
||||
assert.Equal(5, queue.Size())
|
||||
}
|
||||
|
||||
func TestCircularQueue_Back(t *testing.T) {
|
||||
@@ -81,19 +81,19 @@ func TestCircularQueue_Back(t *testing.T) {
|
||||
queue := NewCircularQueue[int](6)
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.EnQueue(4)
|
||||
queue.EnQueue(5)
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
queue.Enqueue(4)
|
||||
queue.Enqueue(5)
|
||||
|
||||
queue.Print()
|
||||
assert.Equal(5, queue.Back())
|
||||
|
||||
queue.DeQueue()
|
||||
queue.DeQueue()
|
||||
queue.EnQueue(6)
|
||||
queue.EnQueue(7)
|
||||
queue.Dequeue()
|
||||
queue.Dequeue()
|
||||
queue.Enqueue(6)
|
||||
queue.Enqueue(7)
|
||||
|
||||
queue.Print()
|
||||
assert.Equal(7, queue.Back())
|
||||
@@ -103,7 +103,7 @@ func TestCircularQueue_Contain(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Contain")
|
||||
|
||||
queue := NewCircularQueue[int](2)
|
||||
queue.EnQueue(1)
|
||||
queue.Enqueue(1)
|
||||
assert.Equal(true, queue.Contain(1))
|
||||
assert.Equal(false, queue.Contain(2))
|
||||
}
|
||||
@@ -113,34 +113,34 @@ func TestCircularQueue_Clear(t *testing.T) {
|
||||
|
||||
queue := NewCircularQueue[int](3)
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
assert.Equal(0, queue.Length())
|
||||
assert.Equal(0, queue.Size())
|
||||
|
||||
queue.EnQueue(1)
|
||||
queue.Enqueue(1)
|
||||
assert.Equal(false, queue.IsEmpty())
|
||||
assert.Equal(1, queue.Length())
|
||||
assert.Equal(1, queue.Size())
|
||||
|
||||
queue.Clear()
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
assert.Equal(0, queue.Length())
|
||||
assert.Equal(0, queue.Size())
|
||||
}
|
||||
|
||||
func TestCircularQueue_Data(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Data")
|
||||
|
||||
queue := NewCircularQueue[int](6)
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.EnQueue(4)
|
||||
queue.EnQueue(5)
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
queue.Enqueue(4)
|
||||
queue.Enqueue(5)
|
||||
|
||||
queue.Print()
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
|
||||
|
||||
queue.DeQueue()
|
||||
queue.DeQueue()
|
||||
queue.EnQueue(6)
|
||||
queue.EnQueue(7)
|
||||
queue.Dequeue()
|
||||
queue.Dequeue()
|
||||
queue.Enqueue(6)
|
||||
queue.Enqueue(7)
|
||||
|
||||
queue.Print()
|
||||
assert.Equal([]int{3, 4, 5, 6, 7}, queue.Data())
|
||||
|
||||
@@ -3,6 +3,7 @@ package datastructure
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/duke-git/lancet/v2/datastructure"
|
||||
)
|
||||
@@ -19,7 +20,7 @@ func NewLinkedQueue[T any]() *LinkedQueue[T] {
|
||||
return &LinkedQueue[T]{head: nil, tail: nil, length: 0}
|
||||
}
|
||||
|
||||
// Data return queue data
|
||||
// Data return slice of queue data
|
||||
func (q *LinkedQueue[T]) Data() []T {
|
||||
res := []T{}
|
||||
current := q.head
|
||||
@@ -41,8 +42,8 @@ func (q *LinkedQueue[T]) IsEmpty() bool {
|
||||
return q.length == 0
|
||||
}
|
||||
|
||||
// EnQueue add element into queue
|
||||
func (q *LinkedQueue[T]) EnQueue(value T) {
|
||||
// Enqueue put element into queue
|
||||
func (q *LinkedQueue[T]) Enqueue(value T) {
|
||||
newNode := datastructure.NewQueueNode(value)
|
||||
|
||||
if q.IsEmpty() {
|
||||
@@ -55,8 +56,8 @@ func (q *LinkedQueue[T]) EnQueue(value T) {
|
||||
q.length++
|
||||
}
|
||||
|
||||
// DeQueue delete head element of queue then return it, if queue is empty, return nil and error
|
||||
func (q *LinkedQueue[T]) DeQueue() (*T, error) {
|
||||
// Dequeue delete head element of queue then return it, if queue is empty, return nil and error
|
||||
func (q *LinkedQueue[T]) Dequeue() (*T, error) {
|
||||
if q.IsEmpty() {
|
||||
return nil, errors.New("queue is empty")
|
||||
}
|
||||
@@ -102,3 +103,15 @@ func (q *LinkedQueue[T]) Print() {
|
||||
info += " ]"
|
||||
fmt.Println(info)
|
||||
}
|
||||
|
||||
// Contain checks if the value is in queue or not
|
||||
func (q *LinkedQueue[T]) Contain(value T) bool {
|
||||
current := q.head
|
||||
for current != nil {
|
||||
if reflect.DeepEqual(current.Value, value) {
|
||||
return true
|
||||
}
|
||||
current = current.Next
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -6,13 +6,13 @@ import (
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestLinkedQueue_EnQueue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_EnQueue")
|
||||
func TestLinkedQueue_Enqueue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_Enqueue")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
|
||||
queue.Print()
|
||||
|
||||
@@ -20,15 +20,15 @@ func TestLinkedQueue_EnQueue(t *testing.T) {
|
||||
assert.Equal(3, queue.Size())
|
||||
}
|
||||
|
||||
func TestLinkedQueue_DeQueue(t *testing.T) {
|
||||
func TestLinkedQueue_Dequeue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_DeQueue")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
|
||||
val, _ := queue.DeQueue()
|
||||
val, _ := queue.Dequeue()
|
||||
|
||||
queue.Print()
|
||||
|
||||
@@ -43,9 +43,9 @@ func TestLinkedQueue_Front(t *testing.T) {
|
||||
_, err := queue.Front()
|
||||
assert.IsNotNil(err)
|
||||
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
|
||||
val, err := queue.Front()
|
||||
assert.Equal(1, *val)
|
||||
@@ -59,9 +59,9 @@ func TestLinkedQueue_Back(t *testing.T) {
|
||||
_, err := queue.Back()
|
||||
assert.IsNotNil(err)
|
||||
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
|
||||
val, err := queue.Back()
|
||||
assert.Equal(3, *val)
|
||||
@@ -74,11 +74,24 @@ func TestLinkedQueue_Clear(t *testing.T) {
|
||||
queue := NewLinkedQueue[int]()
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
assert.Equal(false, queue.IsEmpty())
|
||||
|
||||
queue.Clear()
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
}
|
||||
|
||||
func TestLinkedQueue_Contain(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_Contain")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
|
||||
assert.Equal(true, queue.Contain(1))
|
||||
assert.Equal(false, queue.Contain(4))
|
||||
}
|
||||
|
||||
@@ -29,12 +29,17 @@ func (q *PriorityQueue[T]) IsEmpty() bool {
|
||||
return q.size == 0
|
||||
}
|
||||
|
||||
// Size get number of items in the queue
|
||||
func (q *PriorityQueue[T]) Size() int {
|
||||
return q.size
|
||||
}
|
||||
|
||||
// IsFull checks if the queue capacity is full or not
|
||||
func (q *PriorityQueue[T]) IsFull() bool {
|
||||
return q.size == len(q.items)-1
|
||||
}
|
||||
|
||||
// Data return data slice in the queue
|
||||
// Data return a slice of queue data
|
||||
func (q *PriorityQueue[T]) Data() []T {
|
||||
data := make([]T, q.size)
|
||||
for i := 1; i < q.size+1; i++ {
|
||||
|
||||
@@ -52,9 +52,13 @@ func TestPriorityQueue_Dequeue(t *testing.T) {
|
||||
pq.Enqueue(i)
|
||||
}
|
||||
|
||||
assert.Equal(10, pq.Size())
|
||||
|
||||
val, ok := pq.Dequeue()
|
||||
assert.Equal(true, ok)
|
||||
assert.Equal(10, val)
|
||||
|
||||
assert.Equal([]int{9, 8, 6, 7, 3, 2, 5, 1, 4}, pq.Data())
|
||||
|
||||
assert.Equal(9, pq.Size())
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func (s Set[T]) Contain(value T) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
// Contain checks if set contains other set
|
||||
// ContainAll checks if set contains other set
|
||||
func (s Set[T]) ContainAll(other Set[T]) bool {
|
||||
for k := range other {
|
||||
_, ok := s[k]
|
||||
|
||||
@@ -47,7 +47,7 @@ func (s *ArrayStack[T]) Pop() (*T, error) {
|
||||
return &topItem, nil
|
||||
}
|
||||
|
||||
// Peak return the top element of stack then return it
|
||||
// Peak return the top element of stack
|
||||
func (s *ArrayStack[T]) Peak() (*T, error) {
|
||||
if s.IsEmpty() {
|
||||
return nil, errors.New("stack is empty")
|
||||
|
||||
@@ -24,7 +24,7 @@ func NewBSTree[T any](rootData T, comparator lancetconstraints.Comparator) *BSTr
|
||||
}
|
||||
|
||||
// InsertNode insert data into BSTree
|
||||
func (t *BSTree[T]) InsertNode(data T) {
|
||||
func (t *BSTree[T]) Insert(data T) {
|
||||
root := t.root
|
||||
newNode := datastructure.NewTreeNode(data)
|
||||
if root == nil {
|
||||
@@ -35,7 +35,7 @@ func (t *BSTree[T]) InsertNode(data T) {
|
||||
}
|
||||
|
||||
// DeletetNode delete data into BSTree
|
||||
func (t *BSTree[T]) DeletetNode(data T) {
|
||||
func (t *BSTree[T]) Delete(data T) {
|
||||
deleteTreeNode(t.root, data, t.comparator)
|
||||
}
|
||||
|
||||
@@ -84,20 +84,20 @@ func (t *BSTree[T]) HasSubTree(subTree *BSTree[T]) bool {
|
||||
|
||||
func hasSubTree[T any](superTreeRoot, subTreeRoot *datastructure.TreeNode[T],
|
||||
comparator lancetconstraints.Comparator) bool {
|
||||
res := false
|
||||
result := false
|
||||
|
||||
if superTreeRoot != nil && subTreeRoot != nil {
|
||||
if comparator.Compare(superTreeRoot.Value, subTreeRoot.Value) == 0 {
|
||||
res = isSubTree(superTreeRoot, subTreeRoot, comparator)
|
||||
result = isSubTree(superTreeRoot, subTreeRoot, comparator)
|
||||
}
|
||||
if !res {
|
||||
res = hasSubTree(superTreeRoot.Left, subTreeRoot, comparator)
|
||||
if !result {
|
||||
result = hasSubTree(superTreeRoot.Left, subTreeRoot, comparator)
|
||||
}
|
||||
if !res {
|
||||
res = hasSubTree(superTreeRoot.Right, subTreeRoot, comparator)
|
||||
if !result {
|
||||
result = hasSubTree(superTreeRoot.Right, subTreeRoot, comparator)
|
||||
}
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Print the bstree structure
|
||||
|
||||
@@ -20,13 +20,13 @@ func (c *intComparator) Compare(v1, v2 any) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func TestBSTree_InsertNode(t *testing.T) {
|
||||
func TestBSTree_Insert(t *testing.T) {
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
|
||||
bstree.InsertNode(7)
|
||||
bstree.InsertNode(5)
|
||||
bstree.InsertNode(2)
|
||||
bstree.InsertNode(4)
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
bstree.Print()
|
||||
}
|
||||
@@ -36,10 +36,10 @@ func TestBSTree_PreOrderTraverse(t *testing.T) {
|
||||
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
|
||||
bstree.InsertNode(7)
|
||||
bstree.InsertNode(5)
|
||||
bstree.InsertNode(2)
|
||||
bstree.InsertNode(4)
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
acturl := bstree.PreOrderTraverse()
|
||||
t.Log(acturl)
|
||||
@@ -51,10 +51,10 @@ func TestBSTree_PostOrderTraverse(t *testing.T) {
|
||||
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
|
||||
bstree.InsertNode(7)
|
||||
bstree.InsertNode(5)
|
||||
bstree.InsertNode(2)
|
||||
bstree.InsertNode(4)
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
acturl := bstree.PostOrderTraverse()
|
||||
t.Log(acturl)
|
||||
@@ -66,10 +66,10 @@ func TestBSTree_InOrderTraverse(t *testing.T) {
|
||||
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
|
||||
bstree.InsertNode(7)
|
||||
bstree.InsertNode(5)
|
||||
bstree.InsertNode(2)
|
||||
bstree.InsertNode(4)
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
acturl := bstree.InOrderTraverse()
|
||||
t.Log(acturl)
|
||||
@@ -81,10 +81,10 @@ func TestBSTree_LevelOrderTraverse(t *testing.T) {
|
||||
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
|
||||
bstree.InsertNode(7)
|
||||
bstree.InsertNode(5)
|
||||
bstree.InsertNode(2)
|
||||
bstree.InsertNode(4)
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
bstree.Print()
|
||||
|
||||
@@ -93,19 +93,19 @@ func TestBSTree_LevelOrderTraverse(t *testing.T) {
|
||||
assert.Equal([]int{6, 5, 7, 2, 4}, acturl)
|
||||
}
|
||||
|
||||
func TestBSTree_DeletetNode(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBSTree_DeletetNode")
|
||||
func TestBSTree_Delete(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBSTree_Delete")
|
||||
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
|
||||
bstree.InsertNode(7)
|
||||
bstree.InsertNode(5)
|
||||
bstree.InsertNode(2)
|
||||
bstree.InsertNode(4)
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
bstree.Print()
|
||||
|
||||
bstree.DeletetNode(4)
|
||||
bstree.Delete(4)
|
||||
bstree.Print()
|
||||
acturl1 := bstree.InOrderTraverse()
|
||||
t.Log(acturl1)
|
||||
@@ -124,10 +124,10 @@ func TestBSTree_Depth(t *testing.T) {
|
||||
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
|
||||
bstree.InsertNode(7)
|
||||
bstree.InsertNode(5)
|
||||
bstree.InsertNode(2)
|
||||
bstree.InsertNode(4)
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
bstree.Print()
|
||||
|
||||
@@ -138,17 +138,17 @@ func TestBSTree_IsSubTree(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBSTree_IsSubTree")
|
||||
|
||||
superTree := NewBSTree(8, &intComparator{})
|
||||
superTree.InsertNode(4)
|
||||
superTree.InsertNode(5)
|
||||
superTree.InsertNode(6)
|
||||
superTree.InsertNode(9)
|
||||
superTree.InsertNode(4)
|
||||
superTree.Insert(4)
|
||||
superTree.Insert(5)
|
||||
superTree.Insert(6)
|
||||
superTree.Insert(9)
|
||||
superTree.Insert(4)
|
||||
|
||||
superTree.Print()
|
||||
|
||||
subTree := NewBSTree(5, &intComparator{})
|
||||
subTree.InsertNode(4)
|
||||
subTree.InsertNode(6)
|
||||
subTree.Insert(4)
|
||||
subTree.Insert(6)
|
||||
|
||||
subTree.Print()
|
||||
|
||||
|
||||
@@ -226,8 +226,8 @@ func isSubTree[T any](superTreeRoot, subTreeRoot *datastructure.TreeNode[T], com
|
||||
if comparator.Compare(superTreeRoot.Value, subTreeRoot.Value) != 0 {
|
||||
return false
|
||||
}
|
||||
res := isSubTree(superTreeRoot.Left, subTreeRoot.Left, comparator) && isSubTree(superTreeRoot.Right, subTreeRoot.Right, comparator)
|
||||
return res
|
||||
result := isSubTree(superTreeRoot.Left, subTreeRoot.Left, comparator) && isSubTree(superTreeRoot.Right, subTreeRoot.Right, comparator)
|
||||
return result
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
|
||||
@@ -21,23 +21,20 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [Algorithm](#algorithm)
|
||||
- [Source](#source)
|
||||
- [Usage](#usage)
|
||||
- [Index](#index)
|
||||
- [Documentation](#documentation)
|
||||
- [<span id="BubbleSort">BubbleSort</span>](#bubblesort)
|
||||
- [<span id="InsertionSort">InsertionSort</span>](#insertionsort)
|
||||
- [<span id="SelectionSort">SelectionSort</span>](#selectionsort)
|
||||
- [<span id="ShellSort">ShellSort</span>](#shellsort)
|
||||
- [<span id="QuickSort">QuickSort</span>](#quicksort)
|
||||
- [<span id="HeapSort">HeapSort</span>](#heapsort)
|
||||
- [<span id="MergeSort">MergeSort</span>](#mergesort)
|
||||
- [<span id="CountSort">CountSort</span>](#countsort)
|
||||
- [<span id="BinarySearch">BinarySearch</span>](#binarysearch)
|
||||
- [<span id="BinaryIterativeSearch">BinaryIterativeSearch</span>](#binaryiterativesearch)
|
||||
- [<span id="LinearSearch">LinearSearch</span>](#linearsearch)
|
||||
- [<span id="LRUCache">LRUCache</span>](#lrucache)
|
||||
- [BubbleSort](#BubbleSort)
|
||||
- [InsertionSort](#InsertionSort)
|
||||
- [SelectionSort](#SelectionSort)
|
||||
- [ShellSort](#ShellSort)
|
||||
- [QuickSort](#QuickSort)
|
||||
- [HeapSort](#HeapSort)
|
||||
- [MergeSort](#MergeSort)
|
||||
- [CountSort](#CountSort)
|
||||
- [BinarySearch](#BinarySearch)
|
||||
- [BinaryIterativeSearch](#BinaryIterativeSearch)
|
||||
|
||||
- [LinearSearch](#LinearSearch)
|
||||
- [LRUCache](#LRUCache)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -587,8 +584,8 @@ import (
|
||||
func main() {
|
||||
cache := algorithm.NewLRUCache[int, int](2)
|
||||
|
||||
cache.Put(1, 1)
|
||||
cache.Put(2, 2)
|
||||
cache.Put(1, 1)
|
||||
cache.Put(2, 2)
|
||||
|
||||
_, ok := cache.Get(0) // ok -> false
|
||||
|
||||
|
||||
@@ -21,23 +21,21 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [Algorithm](#algorithm)
|
||||
- [源码](#源码)
|
||||
- [用法](#用法)
|
||||
- [目录](#目录)
|
||||
- [文档](#文档)
|
||||
- [<span id="BubbleSort">BubbleSort</span>](#bubblesort)
|
||||
- [<span id="InsertionSort">InsertionSort</span>](#insertionsort)
|
||||
- [<span id="SelectionSort">SelectionSort</span>](#selectionsort)
|
||||
- [<span id="ShellSort">ShellSort</span>](#shellsort)
|
||||
- [<span id="QuickSort">QuickSort</span>](#quicksort)
|
||||
- [<span id="HeapSort">HeapSort</span>](#heapsort)
|
||||
- [<span id="MergeSort">MergeSort</span>](#mergesort)
|
||||
- [<span id="CountSort">CountSort</span>](#countsort)
|
||||
- [<span id="BinarySearch">BinarySearch</span>](#binarysearch)
|
||||
- [<span id="BinaryIterativeSearch">BinaryIterativeSearch</span>](#binaryiterativesearch)
|
||||
- [<span id="LinearSearch">LinearSearch</span>](#linearsearch)
|
||||
- [<span id="LRUCache">LRUCache</span>](#lrucache)
|
||||
|
||||
- [BubbleSort](#BubbleSort)
|
||||
- [InsertionSort](#InsertionSort)
|
||||
- [SelectionSort](#SelectionSort)
|
||||
- [ShellSort](#ShellSort)
|
||||
- [QuickSort](#QuickSort)
|
||||
- [HeapSort](#HeapSort)
|
||||
- [MergeSort](#MergeSort)
|
||||
|
||||
- [CountSort](#CountSort)
|
||||
- [BinarySearch](#BinarySearch)
|
||||
- [BinaryIterativeSearch](#BinaryIterativeSearch)
|
||||
- [LinearSearch](#LinearSearch)
|
||||
- [LRUCache](#LRUCache)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -587,8 +585,8 @@ import (
|
||||
func main() {
|
||||
cache := algorithm.NewLRUCache[int, int](2)
|
||||
|
||||
cache.Put(1, 1)
|
||||
cache.Put(2, 2)
|
||||
cache.Put(1, 1)
|
||||
cache.Put(2, 2)
|
||||
|
||||
_, ok := cache.Get(0) // ok -> false
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
@@ -133,7 +133,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
@@ -173,14 +173,14 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5)
|
||||
|
||||
for v := range intStream {
|
||||
fmt.Println(v) //1, 2, 1, 2, 1
|
||||
fmt.Println(v) //1, 2, 1, 2, 1
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -209,7 +209,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
fn := func() any {
|
||||
@@ -220,7 +220,7 @@ func main() {
|
||||
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
|
||||
|
||||
for v := range dataStream {
|
||||
fmt.Println(v) //a, a, a
|
||||
fmt.Println(v) //a, a, a
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -248,7 +248,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
sig := func(after time.Duration) <-chan any {
|
||||
sig := func(after time.Duration) <-chan any {
|
||||
c := make(chan interface{})
|
||||
go func() {
|
||||
defer close(c)
|
||||
@@ -296,7 +296,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
@@ -332,7 +332,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
numbers := make(chan any, 5)
|
||||
@@ -347,7 +347,7 @@ func main() {
|
||||
intStream := c.Take(ctx, numbers, 3)
|
||||
|
||||
for val := range intStream {
|
||||
fmt.Println(val) //1, 2, 3
|
||||
fmt.Println(val) //1, 2, 3
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -375,7 +375,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
@@ -383,8 +383,8 @@ func main() {
|
||||
|
||||
out1, out2 := c.Tee(ctx, inStream)
|
||||
for val := range out1 {
|
||||
fmt.Println(val) //1
|
||||
fmt.Println(<-out2) //1
|
||||
fmt.Println(val) //1
|
||||
fmt.Println(<-out2) //1
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -180,7 +180,7 @@ func main() {
|
||||
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5)
|
||||
|
||||
for v := range intStream {
|
||||
fmt.Println(v) //1, 2, 1, 2, 1
|
||||
fmt.Println(v) //1, 2, 1, 2, 1
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -220,7 +220,7 @@ func main() {
|
||||
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
|
||||
|
||||
for v := range dataStream {
|
||||
fmt.Println(v) //a, a, a
|
||||
fmt.Println(v) //a, a, a
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -248,7 +248,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
sig := func(after time.Duration) <-chan any {
|
||||
sig := func(after time.Duration) <-chan any {
|
||||
c := make(chan interface{})
|
||||
go func() {
|
||||
defer close(c)
|
||||
@@ -296,7 +296,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
@@ -332,7 +332,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
numbers := make(chan any, 5)
|
||||
@@ -347,7 +347,7 @@ func main() {
|
||||
intStream := c.Take(ctx, numbers, 3)
|
||||
|
||||
for val := range intStream {
|
||||
fmt.Println(val) //1, 2, 3
|
||||
fmt.Println(val) //1, 2, 3
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -375,7 +375,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
@@ -383,8 +383,8 @@ func main() {
|
||||
|
||||
out1, out2 := c.Tee(ctx, inStream)
|
||||
for val := range out1 {
|
||||
fmt.Println(val) //1
|
||||
fmt.Println(<-out2) //1
|
||||
fmt.Println(val) //1
|
||||
fmt.Println(<-out2) //1
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -24,10 +24,16 @@ import (
|
||||
- [ToBool](#ToBool)
|
||||
- [ToBytes](#ToBytes)
|
||||
- [ToChar](#ToChar)
|
||||
- [ToChannel](#ToChannel)
|
||||
|
||||
- [ToFloat](#ToFloat)
|
||||
- [ToInt](#ToInt)
|
||||
- [ToJson](#ToJson)
|
||||
- [ToMap](#ToMap)
|
||||
- [ToPointer](#ToPointer)
|
||||
- [ToString](#ToString)
|
||||
- [StructToMap](#StructToMap)
|
||||
- [MapToSlice](#MapToSlice)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -191,6 +197,43 @@ func main() {
|
||||
```
|
||||
|
||||
|
||||
### <span id="ToChannel">ToChannel</span>
|
||||
|
||||
<p>Convert a collection of elements to a read-only channels.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToChannel[T any](array []T) <-chan T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ch := convertor.ToChannel([]int{1, 2, 3})
|
||||
|
||||
val1, _ := <-ch
|
||||
fmt.Println(val1) //1
|
||||
|
||||
val2, _ := <-ch
|
||||
fmt.Println(val2) //2
|
||||
|
||||
val3, _ := <-ch
|
||||
fmt.Println(val3) //3
|
||||
|
||||
_, ok := <-ch
|
||||
fmt.Println(ok) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToFloat">ToFloat</span>
|
||||
|
||||
@@ -286,14 +329,14 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="ToString">ToString</span>
|
||||
### <span id="ToMap">ToMap</span>
|
||||
|
||||
<p>Convert interface to string. </p>
|
||||
<p>Convert a slice or an array of structs to a map based on iteratee function. </p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToString(value any) string
|
||||
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -306,9 +349,46 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("%q", convertor.ToString(1)) //"1"
|
||||
fmt.Printf("%q", convertor.ToString(1.1)) //"1.1"
|
||||
fmt.Printf("%q", convertor.ToString([]int{1, 2, 3})) //"[1,2,3]"
|
||||
type Message struct {
|
||||
name string
|
||||
code int
|
||||
}
|
||||
messages := []Message{
|
||||
{name: "Hello", code: 100},
|
||||
{name: "Hi", code: 101},
|
||||
}
|
||||
result := convertor.ToMap(messages, func(msg Message) (int, string) {
|
||||
return msg.code, msg.name
|
||||
})
|
||||
|
||||
fmt.Println(result) //{100: "Hello", 101: "Hi"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToPointer">ToPointer</span>
|
||||
|
||||
<p>Returns a pointer to passed value. </p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToPointer[T any](value T) *T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := convertor.ToPointer(123)
|
||||
fmt.Println(*result) //123
|
||||
}
|
||||
```
|
||||
|
||||
@@ -346,4 +426,35 @@ func main() {
|
||||
|
||||
fmt.Printf("type: %T, value: %s", pm, pm) //type: map[string]interface {}, value: map[name:test]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="MapToSlice">MapToSlice</span>
|
||||
|
||||
<p>Convert a map to a slice based on iteratee function.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
result := MapToSlice(aMap, func(key string, value int) string {
|
||||
return key + ":" + strconv.Itoa(value)
|
||||
})
|
||||
|
||||
fmt.Println(result) //[]string{"a:1", "b:2", "c:3"}
|
||||
}
|
||||
```
|
||||
@@ -26,10 +26,16 @@ import (
|
||||
- [ToBool](#ToBool)
|
||||
- [ToBytes](#ToBytes)
|
||||
- [ToChar](#ToChar)
|
||||
- [ToChannel](#ToChannel)
|
||||
|
||||
- [ToFloat](#ToFloat)
|
||||
- [ToInt](#ToInt)
|
||||
- [ToJson](#ToJson)
|
||||
- [ToMap](#ToMap)
|
||||
- [ToPointer](#ToPointer)
|
||||
- [ToString](#ToString)
|
||||
- [StructToMap](#StructToMap)
|
||||
- [MapToSlice](#MapToSlice)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -194,6 +200,44 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="ToChannel">ToChannel</span>
|
||||
|
||||
<p>将切片转为只读channel</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToChannel[T any](array []T) <-chan T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ch := convertor.ToChannel([]int{1, 2, 3})
|
||||
|
||||
val1, _ := <-ch
|
||||
fmt.Println(val1) //1
|
||||
|
||||
val2, _ := <-ch
|
||||
fmt.Println(val2) //2
|
||||
|
||||
val3, _ := <-ch
|
||||
fmt.Println(val3) //3
|
||||
|
||||
_, ok := <-ch
|
||||
fmt.Println(ok) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToFloat">ToFloat</span>
|
||||
|
||||
<p>将interface转成float64类型,如果参数无法转换,会返回0和error</p>
|
||||
@@ -229,7 +273,7 @@ func main() {
|
||||
|
||||
### <span id="ToInt">ToInt</span>
|
||||
|
||||
<p>将interface转成intt64类型,如果参数无法转换,会返回0和error</p>
|
||||
<p>将interface转成int64类型,如果参数无法转换,会返回0和error</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -288,6 +332,71 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="ToMap">ToMap</span>
|
||||
|
||||
<p>将切片转为map</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Message struct {
|
||||
name string
|
||||
code int
|
||||
}
|
||||
messages := []Message{
|
||||
{name: "Hello", code: 100},
|
||||
{name: "Hi", code: 101},
|
||||
}
|
||||
result := convertor.ToMap(messages, func(msg Message) (int, string) {
|
||||
return msg.code, msg.name
|
||||
})
|
||||
|
||||
fmt.Println(result) //{100: "Hello", 101: "Hi"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToPointer">ToPointer</span>
|
||||
|
||||
<p>返回传入值的指针</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToPointer[T any](value T) *T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := convertor.ToPointer(123)
|
||||
fmt.Println(*result) //123
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToString">ToString</span>
|
||||
|
||||
<p>将interface转成字符串</p>
|
||||
@@ -348,4 +457,35 @@ func main() {
|
||||
|
||||
fmt.Printf("type: %T, value: %s", pm, pm) //type: map[string]interface {}, value: map[name:test]
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="MapToSlice">MapToSlice</span>
|
||||
|
||||
<p>map中key和value执行函数iteratee后,转为切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
result := MapToSlice(aMap, func(key string, value int) string {
|
||||
return key + ":" + strconv.Itoa(value)
|
||||
})
|
||||
|
||||
fmt.Println(result) //[]string{"a:1", "b:2", "c:3"}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -85,7 +85,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -115,9 +115,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesEcbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesEcbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -145,7 +145,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -176,9 +176,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -207,7 +207,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCtrCrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCtrCrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -239,7 +239,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -271,7 +271,7 @@ func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -300,7 +300,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -330,9 +330,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesOfbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesOfbDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
@@ -360,7 +360,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
base64Str := cryptor.Base64StdEncode("hello world")
|
||||
base64Str := cryptor.Base64StdEncode("hello world")
|
||||
fmt.Println(base64Str) //aGVsbG8gd29ybGQ=
|
||||
}
|
||||
```
|
||||
@@ -417,7 +417,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -448,9 +448,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byt(key)
|
||||
decrypted := cryptor.DesEcbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.DesEcbDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
@@ -480,7 +480,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byt(key)
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -511,7 +511,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byt(key)
|
||||
decrypted := cryptor.DesCbcDecrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -543,7 +543,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCtrCrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesCtrCrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -575,7 +575,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byt(key)
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -605,9 +605,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byt(key)
|
||||
decrypted := cryptor.DesCfbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.DesCfbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -636,7 +636,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -666,9 +666,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesOfbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.DesOfbDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
@@ -725,8 +725,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha1("hello world", "12345"))
|
||||
fmt.Println(s) //3826f812255d8683f051ee97346d1359234d5dbd
|
||||
s := cryptor.HmacSha1("hello world", "12345"))
|
||||
fmt.Println(s) //3826f812255d8683f051ee97346d1359234d5dbd
|
||||
}
|
||||
```
|
||||
|
||||
@@ -753,8 +753,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha256("hello world", "12345"))
|
||||
fmt.Println(s) //9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8
|
||||
s := cryptor.HmacSha256("hello world", "12345"))
|
||||
fmt.Println(s) //9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8
|
||||
}
|
||||
```
|
||||
|
||||
@@ -781,8 +781,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha512("hello world", "12345"))
|
||||
fmt.Println(s)
|
||||
s := cryptor.HmacSha512("hello world", "12345"))
|
||||
fmt.Println(s)
|
||||
//5b1563ac4e9b49c9ada8ccb232588fc4f0c30fd12f756b3a0b95af4985c236ca60925253bae10ce2c6bf9af1c1679b51e5395ff3d2826c0a2c7c0d72225d4175
|
||||
}
|
||||
```
|
||||
@@ -810,8 +810,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Md5String("hello"))
|
||||
fmt.Println(s) //5d41402abc4b2a76b9719d911017c592
|
||||
s := cryptor.Md5String("hello"))
|
||||
fmt.Println(s) //5d41402abc4b2a76b9719d911017c592
|
||||
}
|
||||
```
|
||||
|
||||
@@ -838,8 +838,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Md5File("./main.go"))
|
||||
fmt.Println(s)
|
||||
s := cryptor.Md5File("./main.go"))
|
||||
fmt.Println(s)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -866,8 +866,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha1("hello world"))
|
||||
fmt.Println(s) //2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
|
||||
s := cryptor.Sha1("hello world"))
|
||||
fmt.Println(s) //2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
|
||||
}
|
||||
```
|
||||
|
||||
@@ -894,8 +894,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha256("hello world"))
|
||||
fmt.Println(s) //b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
|
||||
s := cryptor.Sha256("hello world"))
|
||||
fmt.Println(s) //b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
|
||||
}
|
||||
```
|
||||
|
||||
@@ -922,7 +922,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha512("hello world"))
|
||||
s := cryptor.Sha512("hello world"))
|
||||
fmt.Println(s) //309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f
|
||||
}
|
||||
```
|
||||
@@ -950,10 +950,10 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -980,14 +980,14 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
data := []byte("hello world")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
@@ -1016,14 +1016,14 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
data := []byte("hello world")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -115,9 +115,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesEcbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesEcbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -145,7 +145,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -176,9 +176,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
@@ -208,7 +208,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCtrCrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCtrCrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -240,7 +240,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -270,9 +270,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -301,7 +301,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -331,9 +331,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesOfbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesOfbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -360,7 +360,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
base64Str := cryptor.Base64StdEncode("hello world")
|
||||
base64Str := cryptor.Base64StdEncode("hello world")
|
||||
fmt.Println(base64Str) //aGVsbG8gd29ybGQ=
|
||||
}
|
||||
```
|
||||
@@ -388,7 +388,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := cryptor.Base64StdDecode("aGVsbG8gd29ybGQ=")
|
||||
str := cryptor.Base64StdDecode("aGVsbG8gd29ybGQ=")
|
||||
fmt.Println(str) //hello world
|
||||
}
|
||||
```
|
||||
@@ -417,7 +417,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -448,7 +448,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesEcbDecrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -480,7 +480,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -511,7 +511,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesCbcDecrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -543,7 +543,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCtrCrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesCtrCrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -575,7 +575,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -605,7 +605,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesCfbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
@@ -636,7 +636,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -666,7 +666,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesOfbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
@@ -696,8 +696,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacMd5("hello world", "12345"))
|
||||
fmt.Println(s) //5f4c9faaff0a1ad3007d9ddc06abe36d
|
||||
s := cryptor.HmacMd5("hello world", "12345"))
|
||||
fmt.Println(s) //5f4c9faaff0a1ad3007d9ddc06abe36d
|
||||
}
|
||||
```
|
||||
|
||||
@@ -724,8 +724,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha1("hello world", "12345"))
|
||||
fmt.Println(s) //3826f812255d8683f051ee97346d1359234d5dbd
|
||||
s := cryptor.HmacSha1("hello world", "12345"))
|
||||
fmt.Println(s) //3826f812255d8683f051ee97346d1359234d5dbd
|
||||
}
|
||||
```
|
||||
|
||||
@@ -752,8 +752,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha256("hello world", "12345"))
|
||||
fmt.Println(s) //9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8
|
||||
s := cryptor.HmacSha256("hello world", "12345"))
|
||||
fmt.Println(s) //9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8
|
||||
}
|
||||
```
|
||||
|
||||
@@ -780,8 +780,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha512("hello world", "12345"))
|
||||
fmt.Println(s)
|
||||
s := cryptor.HmacSha512("hello world", "12345"))
|
||||
fmt.Println(s)
|
||||
//5b1563ac4e9b49c9ada8ccb232588fc4f0c30fd12f756b3a0b95af4985c236ca60925253bae10ce2c6bf9af1c1679b51e5395ff3d2826c0a2c7c0d72225d4175
|
||||
}
|
||||
```
|
||||
@@ -809,8 +809,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Md5String("hello"))
|
||||
fmt.Println(s) //5d41402abc4b2a76b9719d911017c592
|
||||
s := cryptor.Md5String("hello"))
|
||||
fmt.Println(s) //5d41402abc4b2a76b9719d911017c592
|
||||
}
|
||||
```
|
||||
|
||||
@@ -837,8 +837,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Md5File("./main.go"))
|
||||
fmt.Println(s)
|
||||
s := cryptor.Md5File("./main.go"))
|
||||
fmt.Println(s)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -865,8 +865,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha1("hello world"))
|
||||
fmt.Println(s) //2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
|
||||
s := cryptor.Sha1("hello world"))
|
||||
fmt.Println(s) //2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
|
||||
}
|
||||
```
|
||||
|
||||
@@ -893,8 +893,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha256("hello world"))
|
||||
fmt.Println(s) //b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
|
||||
s := cryptor.Sha256("hello world"))
|
||||
fmt.Println(s) //b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
|
||||
}
|
||||
```
|
||||
|
||||
@@ -921,8 +921,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha512("hello world"))
|
||||
fmt.Println(s) //309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f
|
||||
s := cryptor.Sha512("hello world"))
|
||||
fmt.Println(s) //309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f
|
||||
}
|
||||
```
|
||||
|
||||
@@ -949,10 +949,10 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -979,11 +979,11 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
data := []byte("hello world")
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
data := []byte("hello world")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
@@ -1013,11 +1013,11 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
data := []byte("hello world")
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
data := []byte("hello world")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
|
||||
364
docs/datastructure/heap.md
Normal file
364
docs/datastructure/heap.md
Normal file
@@ -0,0 +1,364 @@
|
||||
# Heap
|
||||
Heap is a binary heap tree implemented by slice.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/heap/maxheap.go](https://github.com/duke-git/lancet/blob/main/datastructure/heap/maxheap.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage
|
||||
```go
|
||||
import (
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
|
||||
- [MaxHeap](#MaxHeap)
|
||||
- [Push](#Push)
|
||||
- [Pop](#Pop)
|
||||
- [Peek](#Peek)
|
||||
- [Data](#Data)
|
||||
- [Size](#Size)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
### 1. MaxHeap
|
||||
MaxHeap is a binary heap tree implemented by slice, The key of the root node is both greater than or equal to the key value of the left subtree and greater than or equal to the key value of the right subtree.
|
||||
|
||||
### <span id="NewMaxHeap">NewMaxHeap</span>
|
||||
<p>Return a NewMaxHeap pointer instance.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type MaxHeap[T any] struct {
|
||||
data []T
|
||||
comparator lancetconstraints.Comparator
|
||||
}
|
||||
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
fmt.Println(maxHeap)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Push">Push</span>
|
||||
<p>Push value into the heap</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Push(value T)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.Data()) //[]int{12, 9, 11, 4, 8, 10, 7, 1, 3, 5, 6, 2}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Pop">Pop</span>
|
||||
<p>Pop return the largest value, and remove it from the heap if heap is empty, return zero value and fasle</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Pop() (T, bool)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
val, ok := maxHeap.Pop()
|
||||
|
||||
fmt.Println(val) //12
|
||||
fmt.Println(ok) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Peek">Peek</span>
|
||||
<p>Return the largest element from the heap without removing it, if heap is empty, it returns zero value and false.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Peek() (T, bool)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
val, ok := maxHeap.Peek()
|
||||
|
||||
fmt.Println(val) //12
|
||||
fmt.Println(maxHeap.Size()) //12
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Data">Data</span>
|
||||
<p>Return all element of the heap</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Data() []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.Data()) //[]int{12, 9, 11, 4, 8, 10, 7, 1, 3, 5, 6, 2}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Size">Size</span>
|
||||
<p>Return the number of elements in the heap</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Size() int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.Size()) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="PrintStructure">PrintStructure</span>
|
||||
<p>Print the tree structure of the heap</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) PrintStructure()
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.PrintStructure())
|
||||
// 12
|
||||
// 9 11
|
||||
// 4 8 10 7
|
||||
// 1 3 5 6 2
|
||||
}
|
||||
```
|
||||
364
docs/datastructure/heap_zh-CN.md
Normal file
364
docs/datastructure/heap_zh-CN.md
Normal file
@@ -0,0 +1,364 @@
|
||||
# Heap
|
||||
堆,切片实现的二叉堆数据结构。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/heap/maxheap.go](https://github.com/duke-git/lancet/blob/main/datastructure/heap/maxheap.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法
|
||||
```go
|
||||
import (
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [MaxHeap](#MaxHeap)
|
||||
- [Push](#Push)
|
||||
- [Pop](#Pop)
|
||||
- [Peek](#Peek)
|
||||
- [Data](#Data)
|
||||
- [Size](#Size)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## API文档
|
||||
|
||||
### 1. MaxHeap
|
||||
MaxHeap是通过slice实现的二叉堆树,根节点的key既大于等于左子树的key值且大于等于右子树的key值。
|
||||
|
||||
### <span id="NewMaxHeap">NewMaxHeap</span>
|
||||
<p>返回NewMaxHeap指针实例</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type MaxHeap[T any] struct {
|
||||
data []T
|
||||
comparator lancetconstraints.Comparator
|
||||
}
|
||||
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
fmt.Println(maxHeap)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Push">Push</span>
|
||||
<p>向堆中插入数据</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Push(value T)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.Data()) //[]int{12, 9, 11, 4, 8, 10, 7, 1, 3, 5, 6, 2}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Pop">Pop</span>
|
||||
<p>返回堆中最大值并将其从堆中删除,如果堆为空,返回零值并返回false</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Pop() (T, bool)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
val, ok := maxHeap.Pop()
|
||||
|
||||
fmt.Println(val) //12
|
||||
fmt.Println(ok) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Peek">Peek</span>
|
||||
<p>返回堆中最大值,如果堆为空,返回零值并返回false</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Peek() (T, bool)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
val, ok := maxHeap.Peek()
|
||||
|
||||
fmt.Println(val) //12
|
||||
fmt.Println(maxHeap.Size()) //12
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Data">Data</span>
|
||||
<p>返回堆中全部元素的切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Data() []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.Data()) //[]int{12, 9, 11, 4, 8, 10, 7, 1, 3, 5, 6, 2}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Size">Size</span>
|
||||
<p>返回堆中元素的数量</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Size() int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.Size()) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="PrintStructure">PrintStructure</span>
|
||||
<p>打印堆的树形结构</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) PrintStructure()
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.PrintStructure())
|
||||
// 12
|
||||
// 9 11
|
||||
// 4 8 10 7
|
||||
// 1 3 5 6 2
|
||||
}
|
||||
```
|
||||
1019
docs/datastructure/linklist.md
Normal file
1019
docs/datastructure/linklist.md
Normal file
File diff suppressed because it is too large
Load Diff
1019
docs/datastructure/linklist_zh-CN.md
Normal file
1019
docs/datastructure/linklist_zh-CN.md
Normal file
File diff suppressed because it is too large
Load Diff
713
docs/datastructure/list.md
Normal file
713
docs/datastructure/list.md
Normal file
@@ -0,0 +1,713 @@
|
||||
# List
|
||||
List is a linear table, implemented with slice.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/list/list.go](https://github.com/duke-git/lancet/blob/main/datastructure/list/list.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage
|
||||
```go
|
||||
import (
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
|
||||
- [NewList](#NewList)
|
||||
- [Contain](#Contain)
|
||||
- [Data](#Data)
|
||||
- [ValueOf](#ValueOf)
|
||||
- [IndexOf](#IndexOf)
|
||||
- [Push](#Push)
|
||||
- [PopFirst](#PopFirst)
|
||||
- [PopLast](#PopLast)
|
||||
- [DeleteAt](#DeleteAt)
|
||||
- [InsertAt](#InsertAt)
|
||||
- [UpdateAt](#UpdateAt)
|
||||
- [Equal](#Equal)
|
||||
- [IsEmpty](#IsEmpty)
|
||||
- [Clear](#Clear)
|
||||
- [Clone](#Clone)
|
||||
- [Merge](#Merge)
|
||||
- [Size](#Size)
|
||||
- [Swap](#Swap)
|
||||
- [Reverse](#Reverse)
|
||||
- [Unique](#Unique)
|
||||
- [Union](#Union)
|
||||
- [Intersection](#Intersection)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
### <span id="NewList">NewList</span>
|
||||
<p>List is a linear table, implemented with slice.
|
||||
NewList function return a list pointer</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type List[T any] struct {
|
||||
data []T
|
||||
}
|
||||
func NewList[T any](data []T) *List[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
fmt.Println(li)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Contain">Contain</span>
|
||||
<p>Check if the value in the list or not</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Contain(value T) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
|
||||
fmt.Println(li.Contain(1)) //true
|
||||
fmt.Println(li.Contain(0)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Data">Data</span>
|
||||
<p>Return slice of list data</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Data() []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
data := li.Data()
|
||||
|
||||
fmt.Println(data) //[]int{1, 2, 3}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ValueOf">ValueOf</span>
|
||||
<p>Return the value pointer at index in list</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) ValueOf(index int) (*T, bool)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
v, ok := li.ValueOf(0)
|
||||
|
||||
fmt.Println(*v) //1
|
||||
fmt.Println(ok) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IndexOf">IndexOf</span>
|
||||
<p>Reture the index of value in the list. if not found return -1</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) IndexOf(value T) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
|
||||
fmt.Println(li.IndexOf(1)) //0
|
||||
fmt.Println(li.IndexOf(0)) //-1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Push">Push</span>
|
||||
<p>Append value to the list</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Push(value T)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
li.Push(4)
|
||||
|
||||
fmt.Println(li.Data()) //[]int{1, 2, 3, 4}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="PopFirst">PopFirst</span>
|
||||
<p>Delete the first value of list and return it</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) PopFirst() (*T, bool)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
v, ok := li.PopFirst()
|
||||
|
||||
fmt.Println(*v) //1
|
||||
fmt.Println(ok) //true
|
||||
fmt.Println(li.Data()) //2, 3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="PopLast">PopFirst</span>
|
||||
<p>Delete the last value of list and return it</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) PopLast() (*T, bool)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
v, ok := li.PopLast()
|
||||
|
||||
fmt.Println(*v) //3
|
||||
fmt.Println(ok) //true
|
||||
fmt.Println(li.Data()) //1, 2
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="DeleteAt">DeleteAt</span>
|
||||
<p>Delete the value of list at index, if index is not between 0 and length of list data, do nothing</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) DeleteAt(index int)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3, 4})
|
||||
|
||||
li.DeleteAt(-1)
|
||||
fmt.Println(li.Data()) //1,2,3,4
|
||||
|
||||
li.DeleteAt(4)
|
||||
fmt.Println(li.Data()) //1,2,3,4
|
||||
|
||||
li.DeleteAt(0)
|
||||
fmt.Println(li.Data()) //2,3,4
|
||||
|
||||
li.DeleteAt(2)
|
||||
fmt.Println(li.Data()) //2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="InsertAt">InsertAt</span>
|
||||
<p>Insert value into list at index, if index is not between 0 and length of list data, do nothing</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) InsertAt(index int, value T)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
|
||||
li.InsertAt(-1, 0)
|
||||
fmt.Println(li.Data()) //1,2,3
|
||||
|
||||
li.InsertAt(4, 0)
|
||||
fmt.Println(li.Data()) //1,2,3
|
||||
|
||||
li.InsertAt(3, 4)
|
||||
fmt.Println(li.Data()) //1,2,3,4
|
||||
|
||||
// li.InsertAt(2, 4)
|
||||
// fmt.Println(li.Data()) //1,2,4,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="UpdateAt">UpdateAt</span>
|
||||
<p>Update value of list at index, index shoud between 0 and list size - 1</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) UpdateAt(index int, value T)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
|
||||
li.UpdateAt(-1, 0)
|
||||
fmt.Println(li.Data()) //1,2,3
|
||||
|
||||
li.UpdateAt(2, 4)
|
||||
fmt.Println(li.Data()) //1,2,4
|
||||
|
||||
li.UpdateAt(3, 5)
|
||||
fmt.Println(li.Data()) //1,2,4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Equal">Equal</span>
|
||||
<p>Compare a list to another list, use reflect.DeepEqual on every element</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Equal(other *List[T]) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li1 := list.NewList([]int{1, 2, 3, 4})
|
||||
li2 := list.NewList([]int{1, 2, 3, 4})
|
||||
li3 := list.NewList([]int{1, 2, 3})
|
||||
|
||||
fmt.Println(li1.Equal(li2)) //true
|
||||
fmt.Println(li1.Equal(li3)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsEmpty">IsEmpty</span>
|
||||
<p>Check if a list is empty or not</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) IsEmpty() bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li1 := list.NewList([]int{1, 2, 3})
|
||||
li2 := list.NewList([]int{})
|
||||
|
||||
fmt.Println(li1.IsEmpty()) //false
|
||||
fmt.Println(li2.IsEmpty()) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Clear">Clear</span>
|
||||
<p>Clear the data of list</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Clear()
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
li.Clear()
|
||||
|
||||
fmt.Println(li.Data()) // empty
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Clone">Clone</span>
|
||||
<p>Return a copy of list</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Clone() *List[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
cloneList := li.Clone()
|
||||
|
||||
fmt.Println(cloneList.Data()) // 1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Merge">Merge</span>
|
||||
<p>Merge two list, return new list, don't change original list</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Merge(other *List[T]) *List[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li1 := list.NewList([]int{1, 2, 3, 4})
|
||||
li2 := list.NewList([]int{4, 5, 6})
|
||||
li3 := li1.Merge(li2)
|
||||
|
||||
fmt.Println(li3.Data()) //1, 2, 3, 4, 4, 5, 6
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Size">Size</span>
|
||||
<p>Return number of list data items</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Size() int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3, 4})
|
||||
|
||||
fmt.Println(li.Size()) //4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Swap">Swap</span>
|
||||
<p>Swap the value at two index in list</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Swap(i, j int)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3, 4})
|
||||
li.Swap(0, 3)
|
||||
|
||||
fmt.Println(li.Data()) //4, 2, 3, 1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Reverse">Reverse</span>
|
||||
<p>Reverse the data item order of list</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Reverse()
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3, 4})
|
||||
li.Reverse()
|
||||
|
||||
fmt.Println(li.Data()) //4, 3, 2, 1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Unique">Unique</span>
|
||||
<p>Remove duplicate items in list</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Unique()
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 2, 3, 4})
|
||||
li.Unique()
|
||||
|
||||
fmt.Println(li.Data()) //1,2,3,4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Union">Union</span>
|
||||
<p>Creates a new list contain all elements in list l and other, remove duplicate element</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Union(other *List[T]) *List[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li1 := list.NewList([]int{1, 2, 3, 4})
|
||||
li2 := list.NewList([]int{4, 5, 6})
|
||||
li3 := li1.Union(li2)
|
||||
|
||||
fmt.Println(li3.Data()) //1,2,3,4,5,6
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Intersection">Intersection</span>
|
||||
<p>Creates a new list whose element both be contained in list l and other</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Intersection(other *List[T]) *List[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li1 := list.NewList([]int{1, 2, 3, 4})
|
||||
li2 := list.NewList([]int{4, 5, 6})
|
||||
li3 := li1.Intersection(li2)
|
||||
|
||||
fmt.Println(li3.Data()) //4
|
||||
}
|
||||
```
|
||||
712
docs/datastructure/list_zh-CN.md
Normal file
712
docs/datastructure/list_zh-CN.md
Normal file
@@ -0,0 +1,712 @@
|
||||
# List
|
||||
List是线性表数据结构, 用go切片实现。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/list/list.go](https://github.com/duke-git/lancet/blob/main/datastructure/list/list.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/datastructure"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [NewList](#NewList)
|
||||
- [Contain](#Contain)
|
||||
- [Data](#Data)
|
||||
- [ValueOf](#ValueOf)
|
||||
- [IndexOf](#IndexOf)
|
||||
- [Push](#Push)
|
||||
- [PopFirst](#PopFirst)
|
||||
- [PopLast](#PopLast)
|
||||
- [DeleteAt](#DeleteAt)
|
||||
- [InsertAt](#InsertAt)
|
||||
- [UpdateAt](#UpdateAt)
|
||||
- [Equal](#Equal)
|
||||
- [IsEmpty](#IsEmpty)
|
||||
- [Clear](#Clear)
|
||||
- [Clone](#Clone)
|
||||
- [Merge](#Merge)
|
||||
- [Size](#Size)
|
||||
- [Swap](#Swap)
|
||||
- [Reverse](#Reverse)
|
||||
- [Unique](#Unique)
|
||||
- [Union](#Union)
|
||||
- [Intersection](#Intersection)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="NewList">NewList</span>
|
||||
<p>返回List指针实例</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type List[T any] struct {
|
||||
data []T
|
||||
}
|
||||
func NewList[T any](data []T) *List[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
fmt.Println(li)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Contain">Contain</span>
|
||||
<p>判断列表中是否包含特定值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Contain(value T) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
|
||||
fmt.Println(li.Contain(1)) //true
|
||||
fmt.Println(li.Contain(0)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Data">Data</span>
|
||||
<p>返回List中所有数据(切片)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Data() []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
data := li.Data()
|
||||
|
||||
fmt.Println(data) //[]int{1, 2, 3}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ValueOf">ValueOf</span>
|
||||
<p>返回列表中索引处的值指针</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) ValueOf(index int) (*T, bool)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
v, ok := li.ValueOf(0)
|
||||
|
||||
fmt.Println(*v) //1
|
||||
fmt.Println(ok) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IndexOf">IndexOf</span>
|
||||
<p>返回列表中值的索引,如果没有找到返回-1</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) IndexOf(value T) int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
|
||||
fmt.Println(li.IndexOf(1)) //0
|
||||
fmt.Println(li.IndexOf(0)) //-1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Push">Push</span>
|
||||
<p>将值附加到列表末尾</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Push(value T)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
li.Push(4)
|
||||
|
||||
fmt.Println(li.Data()) //[]int{1, 2, 3, 4}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="PopFirst">PopFirst</span>
|
||||
<p>删除列表的第一个值并返回该值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) PopFirst() (*T, bool)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
v, ok := li.PopFirst()
|
||||
|
||||
fmt.Println(*v) //1
|
||||
fmt.Println(ok) //true
|
||||
fmt.Println(li.Data()) //2, 3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="PopLast">PopFirst</span>
|
||||
<p>删除列表的最后一个值并返回该值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) PopLast() (*T, bool)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
v, ok := li.PopLast()
|
||||
|
||||
fmt.Println(*v) //3
|
||||
fmt.Println(ok) //true
|
||||
fmt.Println(li.Data()) //1, 2
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="DeleteAt">DeleteAt</span>
|
||||
<p>删除索引处列表的值,如果索引不在0和列表数据长度之间,则不执行任何操作</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) DeleteAt(index int)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3, 4})
|
||||
|
||||
li.DeleteAt(-1)
|
||||
fmt.Println(li.Data()) //1,2,3,4
|
||||
|
||||
li.DeleteAt(4)
|
||||
fmt.Println(li.Data()) //1,2,3,4
|
||||
|
||||
li.DeleteAt(0)
|
||||
fmt.Println(li.Data()) //2,3,4
|
||||
|
||||
li.DeleteAt(2)
|
||||
fmt.Println(li.Data()) //2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="InsertAt">InsertAt</span>
|
||||
<p>在索引处插入值到列表中,如果索引不在 0 和列表数据长度之间,则不执行任何操作</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) InsertAt(index int, value T)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
|
||||
li.InsertAt(-1, 0)
|
||||
fmt.Println(li.Data()) //1,2,3
|
||||
|
||||
li.InsertAt(4, 0)
|
||||
fmt.Println(li.Data()) //1,2,3
|
||||
|
||||
li.InsertAt(3, 4)
|
||||
fmt.Println(li.Data()) //1,2,3,4
|
||||
|
||||
// li.InsertAt(2, 4)
|
||||
// fmt.Println(li.Data()) //1,2,4,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="UpdateAt">UpdateAt</span>
|
||||
<p>更新索引处列表的值,索引应该在0和列表数据长度-1之间</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) UpdateAt(index int, value T)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
|
||||
li.UpdateAt(-1, 0)
|
||||
fmt.Println(li.Data()) //1,2,3
|
||||
|
||||
li.UpdateAt(2, 4)
|
||||
fmt.Println(li.Data()) //1,2,4
|
||||
|
||||
li.UpdateAt(3, 5)
|
||||
fmt.Println(li.Data()) //1,2,4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Equal">Equal</span>
|
||||
<p>比较一个列表和另一个列表,在每个元素上使用 reflect.DeepEqual</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Equal(other *List[T]) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li1 := list.NewList([]int{1, 2, 3, 4})
|
||||
li2 := list.NewList([]int{1, 2, 3, 4})
|
||||
li3 := list.NewList([]int{1, 2, 3})
|
||||
|
||||
fmt.Println(li1.Equal(li2)) //true
|
||||
fmt.Println(li1.Equal(li3)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsEmpty">IsEmpty</span>
|
||||
<p>判断列表是否为空</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) IsEmpty() bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li1 := list.NewList([]int{1, 2, 3})
|
||||
li2 := list.NewList([]int{})
|
||||
|
||||
fmt.Println(li1.IsEmpty()) //false
|
||||
fmt.Println(li2.IsEmpty()) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Clear">Clear</span>
|
||||
<p>清空列表数据</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Clear()
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
li.Clear()
|
||||
|
||||
fmt.Println(li.Data()) // empty
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Clone">Clone</span>
|
||||
<p>返回列表的一个拷贝</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Clone() *List[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
cloneList := li.Clone()
|
||||
|
||||
fmt.Println(cloneList.Data()) // 1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Merge">Merge</span>
|
||||
<p>合并两个列表,返回新的列表</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Merge(other *List[T]) *List[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li1 := list.NewList([]int{1, 2, 3, 4})
|
||||
li2 := list.NewList([]int{4, 5, 6})
|
||||
li3 := li1.Merge(li2)
|
||||
|
||||
fmt.Println(li3.Data()) //1, 2, 3, 4, 4, 5, 6
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Size">Size</span>
|
||||
<p>返回列表数据项的数量</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Size() int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3, 4})
|
||||
|
||||
fmt.Println(li.Size()) //4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Swap">Swap</span>
|
||||
<p>交换列表中两个索引位置的值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Swap(i, j int)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3, 4})
|
||||
li.Swap(0, 3)
|
||||
|
||||
fmt.Println(li.Data()) //4, 2, 3, 1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Reverse">Reverse</span>
|
||||
<p>反转列表的数据项顺序</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Reverse()
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3, 4})
|
||||
li.Reverse()
|
||||
|
||||
fmt.Println(li.Data()) //4, 3, 2, 1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Unique">Unique</span>
|
||||
<p>列表去除重复数据项</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Unique()
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 2, 3, 4})
|
||||
li.Unique()
|
||||
|
||||
fmt.Println(li.Data()) //1,2,3,4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Union">Union</span>
|
||||
<p>两个列表取并集,去除重复数据项</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Union(other *List[T]) *List[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li1 := list.NewList([]int{1, 2, 3, 4})
|
||||
li2 := list.NewList([]int{4, 5, 6})
|
||||
li3 := li1.Union(li2)
|
||||
|
||||
fmt.Println(li3.Data()) //1,2,3,4,5,6
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Intersection">Intersection</span>
|
||||
<p>两个列表取交集</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Intersection(other *List[T]) *List[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li1 := list.NewList([]int{1, 2, 3, 4})
|
||||
li2 := list.NewList([]int{4, 5, 6})
|
||||
li3 := li1.Intersection(li2)
|
||||
|
||||
fmt.Println(li3.Data()) //4
|
||||
}
|
||||
```
|
||||
1387
docs/datastructure/queue.md
Normal file
1387
docs/datastructure/queue.md
Normal file
File diff suppressed because it is too large
Load Diff
1387
docs/datastructure/queue_zh-CN.md
Normal file
1387
docs/datastructure/queue_zh-CN.md
Normal file
File diff suppressed because it is too large
Load Diff
489
docs/datastructure/set.md
Normal file
489
docs/datastructure/set.md
Normal file
@@ -0,0 +1,489 @@
|
||||
# Set
|
||||
Set is a data container, like list, but elements of set is not duplicate.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go](https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage
|
||||
```go
|
||||
import (
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
|
||||
- [NewSet](#NewSet)
|
||||
- [Values](#Values)
|
||||
- [Add](#Add)
|
||||
- [Delete](#Delete)
|
||||
- [Contain](#Contain)
|
||||
- [ContainAll](#ContainAll)
|
||||
- [Clone](#Clone)
|
||||
- [Size](#Size)
|
||||
- [Equal](#Equal)
|
||||
- [Iterate](#Iterate)
|
||||
- [IsEmpty](#IsEmpty)
|
||||
- [Union](#Union)
|
||||
- [Intersection](#Intersection)
|
||||
|
||||
- [SymmetricDifference](#SymmetricDifference)
|
||||
- [Minus](#Minus)
|
||||
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
### <span id="NewSet">NewSet</span>
|
||||
<p>Make a Set instance</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type Set[T comparable] map[T]bool
|
||||
func NewSet[T comparable](values ...T) Set[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int](1,2,2,3)
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Values">Values</span>
|
||||
<p>Return slice of all set data</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Values() []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int](1,2,2,3)
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Add">Add</span>
|
||||
<p>Add value to set</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Add(values ...T)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Delete">Delete</span>
|
||||
<p>Delete value in set</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Delete(values ...T)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
set.Delete(3)
|
||||
fmt.Println(st.Values()) //1,2
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Contain">Contain</span>
|
||||
<p>Check if value is in set or not</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Contain(value T) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
fmt.Println(st.Contain(1)) //true
|
||||
fmt.Println(st.Contain(4)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ContainAll">ContainAll</span>
|
||||
<p>Checks if set contains another set</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) ContainAll(other Set[T]) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(1, 2)
|
||||
set3 := set.NewSet(1, 2, 3, 4)
|
||||
|
||||
fmt.Println(set1.ContainAll(set2)) //true
|
||||
fmt.Println(set1.ContainAll(set3)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Size">Size</span>
|
||||
<p>Get the number of elements in set</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Size() int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
|
||||
fmt.Println(set1.Size()) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Clone">Clone</span>
|
||||
<p>Make a copy of set</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Clone() Set[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set1.Clone()
|
||||
|
||||
fmt.Println(set1.Size() == set2.Size()) //true
|
||||
fmt.Println(set1.ContainAll(set2)) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Equal">Equal</span>
|
||||
<p>Check if two sets has same elements or not</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Equal(other Set[T]) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(1, 2, 3)
|
||||
set3 := set.NewSet(1, 2, 3, 4)
|
||||
|
||||
fmt.Println(set1.Equal(set2)) //true
|
||||
fmt.Println(set1.Equal(set3)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Iterate">Iterate</span>
|
||||
<p>Call function by every element of set</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Iterate(fn func(value T))
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
arr := []int{}
|
||||
set.Iterate(func(value int) {
|
||||
arr = append(arr, value)
|
||||
})
|
||||
|
||||
fmt.Println(arr) //1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsEmpty">IsEmpty</span>
|
||||
<p>Check if the set is empty or not</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) IsEmpty() bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet()
|
||||
|
||||
fmt.Println(set1.IsEmpty()) //false
|
||||
fmt.Println(set2.IsEmpty()) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Union">Union</span>
|
||||
<p>Create a new set contain all element of set s and other</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Union(other Set[T]) Set[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set1.Union(set2)
|
||||
|
||||
fmt.Println(set3.Values()) //1,2,3,4,5
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Intersection">Intersection</span>
|
||||
<p>Create a new set whose element both be contained in set s and other</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Intersection(other Set[T]) Set[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set1.Intersection(set2)
|
||||
|
||||
fmt.Println(set3.Values()) //2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="SymmetricDifference">SymmetricDifference</span>
|
||||
<p>Create a new set whose element is in set1 or set2, but not in both set1 and set2</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) SymmetricDifference(other Set[T]) Set[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set1.SymmetricDifference(set2)
|
||||
|
||||
fmt.Println(set3.Values()) //1,4,5
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Minus">Minus</span>
|
||||
<p>Create an set of whose element in origin set but not in compared set</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Minus(comparedSet Set[T]) Set[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set.NewSet(2, 3)
|
||||
|
||||
res1 := set1.Minus(set2)
|
||||
fmt.Println(res1.Values()) //1
|
||||
|
||||
res2 := set2.Minus(set3)
|
||||
fmt.Println(res2.Values()) //4,5
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
489
docs/datastructure/set_zh-CN.md
Normal file
489
docs/datastructure/set_zh-CN.md
Normal file
@@ -0,0 +1,489 @@
|
||||
# Set
|
||||
Set集合数据结构,类似列表。Set中元素不重复。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go](https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法
|
||||
```go
|
||||
import (
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [NewSet](#NewSet)
|
||||
- [Values](#Values)
|
||||
- [Add](#Add)
|
||||
- [Delete](#Delete)
|
||||
- [Contain](#Contain)
|
||||
- [ContainAll](#ContainAll)
|
||||
- [Clone](#Clone)
|
||||
- [Size](#Size)
|
||||
- [Equal](#Equal)
|
||||
- [Iterate](#Iterate)
|
||||
- [IsEmpty](#IsEmpty)
|
||||
- [Union](#Union)
|
||||
- [Intersection](#Intersection)
|
||||
|
||||
- [SymmetricDifference](#SymmetricDifference)
|
||||
- [Minus](#Minus)
|
||||
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="NewSet">NewSet</span>
|
||||
<p>返回Set结构体对象</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type Set[T comparable] map[T]bool
|
||||
func NewSet[T comparable](values ...T) Set[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int](1,2,2,3)
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Values">Values</span>
|
||||
<p>获取集合中所有元素的切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Values() []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int](1,2,2,3)
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Add">Add</span>
|
||||
<p>向集合中添加元素</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Add(values ...T)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Delete">Delete</span>
|
||||
<p>删除集合中元素</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Delete(values ...T)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
set.Delete(3)
|
||||
fmt.Println(st.Values()) //1,2
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Contain">Contain</span>
|
||||
<p>判断集合是否包含某个值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Contain(value T) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
fmt.Println(st.Contain(1)) //true
|
||||
fmt.Println(st.Contain(4)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ContainAll">ContainAll</span>
|
||||
<p>判断集合是否包含另一个集合</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) ContainAll(other Set[T]) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(1, 2)
|
||||
set3 := set.NewSet(1, 2, 3, 4)
|
||||
|
||||
fmt.Println(set1.ContainAll(set2)) //true
|
||||
fmt.Println(set1.ContainAll(set3)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Size">Size</span>
|
||||
<p>获取集合中元素的个数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Size() int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
|
||||
fmt.Println(set1.Size()) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Clone">Clone</span>
|
||||
<p>克隆一个集合</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Clone() Set[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set1.Clone()
|
||||
|
||||
fmt.Println(set1.Size() == set2.Size()) //true
|
||||
fmt.Println(set1.ContainAll(set2)) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Equal">Equal</span>
|
||||
<p>比较两个集合是否相等,包含相同元素为相等</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Equal(other Set[T]) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(1, 2, 3)
|
||||
set3 := set.NewSet(1, 2, 3, 4)
|
||||
|
||||
fmt.Println(set1.Equal(set2)) //true
|
||||
fmt.Println(set1.Equal(set3)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Iterate">Iterate</span>
|
||||
<p>迭代结合,在每个元素上调用函数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Iterate(fn func(value T))
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
arr := []int{}
|
||||
set.Iterate(func(value int) {
|
||||
arr = append(arr, value)
|
||||
})
|
||||
|
||||
fmt.Println(arr) //1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsEmpty">IsEmpty</span>
|
||||
<p>判断集合是否为空</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) IsEmpty() bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet()
|
||||
|
||||
fmt.Println(set1.IsEmpty()) //false
|
||||
fmt.Println(set2.IsEmpty()) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Union">Union</span>
|
||||
<p>求两个集合的并集</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Union(other Set[T]) Set[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set1.Union(set2)
|
||||
|
||||
fmt.Println(set3.Values()) //1,2,3,4,5
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Intersection">Intersection</span>
|
||||
<p>求两个集合的交集</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Intersection(other Set[T]) Set[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set1.Intersection(set2)
|
||||
|
||||
fmt.Println(set3.Values()) //2,3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="SymmetricDifference">SymmetricDifference</span>
|
||||
<p>返回一个集合,其中元素在第一个集合或第二个集合中,且不同时存在于两个集合中</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) SymmetricDifference(other Set[T]) Set[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set1.SymmetricDifference(set2)
|
||||
|
||||
fmt.Println(set3.Values()) //1,4,5
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Minus">Minus</span>
|
||||
<p>创建一个集合,其元素在原始集中但不在比较集中</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Minus(comparedSet Set[T]) Set[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set.NewSet(2, 3)
|
||||
|
||||
res1 := set1.Minus(set2)
|
||||
fmt.Println(res1.Values()) //1
|
||||
|
||||
res2 := set2.Minus(set3)
|
||||
fmt.Println(res2.Values()) //4,5
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
611
docs/datastructure/stack.md
Normal file
611
docs/datastructure/stack.md
Normal file
@@ -0,0 +1,611 @@
|
||||
# Stack
|
||||
Stack is an abstract data type that serves as a collection of elements. Elements follow the LIFO principle. FIFO is last-in, first-out, meaning that the most recently produced items are recorded as sold first.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/stack/arraystack.go](https://github.com/duke-git/lancet/blob/main/datastructure/stack/arraystack.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/stack/linkedstack.go](https://github.com/duke-git/lancet/blob/main/datastructure/stack/linkedstack.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage
|
||||
```go
|
||||
import (
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
|
||||
### 1. ArrayStack
|
||||
|
||||
- [NewArrayStack](#NewArrayStack)
|
||||
- [Push](#ArrayStack_Push)
|
||||
- [Pop](#ArrayStack_Pop)
|
||||
- [Peak](#ArrayStack_Peak)
|
||||
- [Data](#ArrayStack_Data)
|
||||
- [Size](#ArrayStack_Size)
|
||||
- [IsEmpty](#ArrayStack_IsEmpty)
|
||||
- [Clear](#ArrayStack_Clear)
|
||||
|
||||
### 2. LinkedStack
|
||||
|
||||
- [NewLinkedStack](#NewLinkedStack)
|
||||
- [Push](#LinkedStack_Push)
|
||||
- [Pop](#LinkedStack_Pop)
|
||||
- [Peak](#LinkedStack_Peak)
|
||||
- [Data](#LinkedStack_Data)
|
||||
- [Size](#LinkedStack_Size)
|
||||
- [IsEmpty](#LinkedStack_IsEmpty)
|
||||
- [Clear](#LinkedStack_Clear)
|
||||
- [Print](#LinkedStack_Print)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
### 1. ArrayStack
|
||||
ArrayStack is a stack implemented by slice.
|
||||
|
||||
### <span id="NewArrayStack">NewArrayStack</span>
|
||||
<p>Return a empty ArrayStack pointer</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type ArrayStack[T any] struct {
|
||||
data []T
|
||||
length int
|
||||
}
|
||||
func NewArrayStack[T any]() *ArrayStack[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
fmt.Println(sk)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_Push">Push</span>
|
||||
<p>Push element into array stack</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) Push(value T)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{3, 2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_Pop">Pop</span>
|
||||
<p>Delete the top element of stack then return it, if stack is empty, return nil and error</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) Pop() (*T, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
val, err := sk.Pop()
|
||||
fmt.Println(err) //nil
|
||||
fmt.Println(*val) //3
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_Peak">Peak</span>
|
||||
<p>Return the top element of array stack</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) Peak() (*T, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
val, err := sk.Peak()
|
||||
fmt.Println(err) //nil
|
||||
fmt.Println(*val) //3
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{3, 2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_Data">Data</span>
|
||||
<p>Return a slice of all data in array stack</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) Data() []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{3, 2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_Size">Size</span>
|
||||
<p>Return number of elements in array stack</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) Size() int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.Size()) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_IsEmpty">IsEmpty</span>
|
||||
<p>Check if array stack is empty or not</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) IsEmpty() bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
fmt.Println(sk.IsEmpty()) //true
|
||||
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.IsEmpty()) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_Clear">Clear</span>
|
||||
<p>Clear all elments in array stack</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) Clear()
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
sk.Clear()
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 2. LinkedStack
|
||||
LinkedStack is a stack implemented by linked list.
|
||||
|
||||
### <span id="NewLinkedStack">NewLinkedStack</span>
|
||||
<p>Return a empty LinkedStack pointer</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type StackNode[T any] struct {
|
||||
Value T
|
||||
Next *StackNode[T]
|
||||
}
|
||||
type LinkedStack[T any] struct {
|
||||
top *datastructure.StackNode[T]
|
||||
length int
|
||||
}
|
||||
func NewLinkedStack[T any]() *LinkedStack[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
fmt.Println(sk)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Push">Push</span>
|
||||
<p>Push element into linked stack</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Push(value T)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{3, 2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Pop">Pop</span>
|
||||
<p>Delete the top element of stack then return it, if stack is empty, return nil and error</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Pop() (*T, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
val, err := sk.Pop()
|
||||
fmt.Println(err) //nil
|
||||
fmt.Println(*val) //3
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Peak">Peak</span>
|
||||
<p>Return the top element of linked stack</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Peak() (*T, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
val, err := sk.Peak()
|
||||
fmt.Println(err) //nil
|
||||
fmt.Println(*val) //3
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{3, 2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Data">Data</span>
|
||||
<p>Return a slice of all data in linked stack</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Data() []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{3, 2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Size">Size</span>
|
||||
<p>Return number of elements in linked stack</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Size() int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.Size()) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_IsEmpty">IsEmpty</span>
|
||||
<p>Check if linked stack is empty or not</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) IsEmpty() bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
fmt.Println(sk.IsEmpty()) //true
|
||||
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.IsEmpty()) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Clear">Clear</span>
|
||||
<p>Clear all elments in linked stack</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Clear()
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
sk.Clear()
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Print">Print</span>
|
||||
<p>Print the structure of a linked stack</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Print()
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
|
||||
sk.Print() //[ &{Value:3 Next:0xc000010260}, &{Value:2 Next:0xc000010250}, &{Value:1 Next:<nil>}, ]
|
||||
}
|
||||
```
|
||||
611
docs/datastructure/stack_zh-CN.md
Normal file
611
docs/datastructure/stack_zh-CN.md
Normal file
@@ -0,0 +1,611 @@
|
||||
# Stack
|
||||
栈数据结构,包括ArrayStack(数组栈)和LinkedStack(链表栈)。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/stack/arraystack.go](https://github.com/duke-git/lancet/blob/main/datastructure/stack/arraystack.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/stack/linkedstack.go](https://github.com/duke-git/lancet/blob/main/datastructure/stack/linkedstack.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法
|
||||
```go
|
||||
import (
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
### 1. ArrayStack(数组栈)
|
||||
|
||||
- [NewArrayStack](#NewArrayStack)
|
||||
- [Push](#ArrayStack_Push)
|
||||
- [Pop](#ArrayStack_Pop)
|
||||
- [Peak](#ArrayStack_Peak)
|
||||
- [Data](#ArrayStack_Data)
|
||||
- [Size](#ArrayStack_Size)
|
||||
- [IsEmpty](#ArrayStack_IsEmpty)
|
||||
- [Clear](#ArrayStack_Clear)
|
||||
|
||||
### 2. LinkedStack(链表栈)
|
||||
|
||||
- [NewLinkedStack](#NewLinkedStack)
|
||||
- [Push](#LinkedStack_Push)
|
||||
- [Pop](#LinkedStack_Pop)
|
||||
- [Peak](#LinkedStack_Peak)
|
||||
- [Data](#LinkedStack_Data)
|
||||
- [Size](#LinkedStack_Size)
|
||||
- [IsEmpty](#LinkedStack_IsEmpty)
|
||||
- [Clear](#LinkedStack_Clear)
|
||||
- [Print](#LinkedStack_Print)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
### 1. ArrayStack
|
||||
用切片实现栈结构
|
||||
|
||||
### <span id="NewArrayStack">NewArrayStack</span>
|
||||
<p>返回ArrayStack指针实例</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type ArrayStack[T any] struct {
|
||||
data []T
|
||||
length int
|
||||
}
|
||||
func NewArrayStack[T any]() *ArrayStack[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
fmt.Println(sk)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_Push">Push</span>
|
||||
<p>将元素加入数组栈</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) Push(value T)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{3, 2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_Pop">Pop</span>
|
||||
<p>删除栈顶元素并返回该元素指针</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) Pop() (*T, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
val, err := sk.Pop()
|
||||
fmt.Println(err) //nil
|
||||
fmt.Println(*val) //3
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_Peak">Peak</span>
|
||||
<p>返回栈顶元素指针</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) Peak() (*T, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
val, err := sk.Peak()
|
||||
fmt.Println(err) //nil
|
||||
fmt.Println(*val) //3
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{3, 2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_Data">Data</span>
|
||||
<p>返回栈中所有元素组成的切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) Data() []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{3, 2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_Size">Size</span>
|
||||
<p>返回栈中元素的数量</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) Size() int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.Size()) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_IsEmpty">IsEmpty</span>
|
||||
<p>判断栈是否为空</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) IsEmpty() bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
fmt.Println(sk.IsEmpty()) //true
|
||||
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.IsEmpty()) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ArrayStack_Clear">Clear</span>
|
||||
<p>清空栈元素,使栈为空</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *ArrayStack[T]) Clear()
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewArrayStack[int]()
|
||||
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
sk.Clear()
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 2. LinkedStack
|
||||
链表实现的栈结构。
|
||||
|
||||
### <span id="NewLinkedStack">NewLinkedStack</span>
|
||||
<p>返回LinkedStack指针实例</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type StackNode[T any] struct {
|
||||
Value T
|
||||
Next *StackNode[T]
|
||||
}
|
||||
type LinkedStack[T any] struct {
|
||||
top *datastructure.StackNode[T]
|
||||
length int
|
||||
}
|
||||
func NewLinkedStack[T any]() *LinkedStack[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
fmt.Println(sk)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Push">Push</span>
|
||||
<p>将元素加入链表栈</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Push(value T)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{3, 2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Pop">Pop</span>
|
||||
<p>删除栈顶元素并返回该元素指针</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Pop() (*T, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
val, err := sk.Pop()
|
||||
fmt.Println(err) //nil
|
||||
fmt.Println(*val) //3
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Peak">Peak</span>
|
||||
<p>返回栈顶元素指针</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Peak() (*T, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
val, err := sk.Peak()
|
||||
fmt.Println(err) //nil
|
||||
fmt.Println(*val) //3
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{3, 2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Data">Data</span>
|
||||
<p>返回栈中所有元素组成的切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Data() []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{3, 2, 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Size">Size</span>
|
||||
<p>返回栈中元素的数量</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Size() int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.Size()) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_IsEmpty">IsEmpty</span>
|
||||
<p>判断栈是否为空</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) IsEmpty() bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
fmt.Println(sk.IsEmpty()) //true
|
||||
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
fmt.Println(sk.IsEmpty()) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Clear">Clear</span>
|
||||
<p>清空栈元素,使栈为空</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Clear()
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
sk.Clear()
|
||||
|
||||
fmt.Println(sk.Data()) //[]int{}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinkedStack_Print">Print</span>
|
||||
<p>打印链表栈结构</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *LinkedStack[T]) Print()
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sk := stack.NewLinkedStack[int]()
|
||||
|
||||
sk.Push(1)
|
||||
sk.Push(2)
|
||||
sk.Push(3)
|
||||
|
||||
|
||||
sk.Print() //[ &{Value:3 Next:0xc000010260}, &{Value:2 Next:0xc000010250}, &{Value:1 Next:<nil>}, ]
|
||||
}
|
||||
```
|
||||
527
docs/datastructure/tree.md
Normal file
527
docs/datastructure/tree.md
Normal file
@@ -0,0 +1,527 @@
|
||||
# Tree
|
||||
Tree is a collection of tree nodes. Each tree node has a value, a left pointer point to left node and a right pointer point to right node.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/tree/bstree.go](https://github.com/duke-git/lancet/blob/main/datastructure/tree/bstree.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage
|
||||
```go
|
||||
import (
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
|
||||
### 1. BSTree
|
||||
|
||||
- [NewBSTree](#NewBSTree)
|
||||
- [Insert](#BSTree_Insert)
|
||||
- [Delete](#BSTree_Delete)
|
||||
- [PreOrderTraverse](#BSTree_PreOrderTraverse)
|
||||
- [InOrderTraverse](#BSTree_InOrderTraverse)
|
||||
- [PostOrderTraverse](#BSTree_PostOrderTraverse)
|
||||
|
||||
- [LevelOrderTraverse](#BSTree_LevelOrderTraverse)
|
||||
- [Depth](#BSTree_Depth)
|
||||
- [HasSubTree](#BSTree_HasSubTree)
|
||||
- [Print](#BSTree_Print)
|
||||
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
## 1. BSTree
|
||||
BSTree is a binary search tree data structure in which each node has at two children, which are referred to as the left child and the right child. In BSTree: leftNode < rootNode < rightNode. Type T should implements Compare function in lancetconstraints.Comparator interface.
|
||||
|
||||
### <span id="NewBSTree">NewBSTree</span>
|
||||
<p>Make a BSTree pointer instance</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func NewBSTree[T any](rootData T, comparator lancetconstraints.Comparator) *BSTree[T]
|
||||
|
||||
type BSTree[T any] struct {
|
||||
root *datastructure.TreeNode[T]
|
||||
comparator lancetconstraints.Comparator
|
||||
}
|
||||
|
||||
type TreeNode[T any] struct {
|
||||
Value T
|
||||
Left *TreeNode[T]
|
||||
Right *TreeNode[T]
|
||||
}
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
fmt.Println(bstree) //
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_Insert">Insert</span>
|
||||
<p>Insert value into binary search tree</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) Insert(data T)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.PreOrderTraverse()) //6, 5, 2, 4, 7
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_Delete">Delete</span>
|
||||
<p>Delete value of binary search tree</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) Delete(data T)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
bstree.Delete(4)
|
||||
|
||||
fmt.Println(bstree.PreOrderTraverse()) //2, 5, 6, 7
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_PreOrderTraverse">PreOrderTraverse</span>
|
||||
<p>Traverse tree nodes in pre order</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) PreOrderTraverse() []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.PreOrderTraverse()) //6, 5, 2, 4, 7
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_InOrderTraverse">InOrderTraverse</span>
|
||||
<p>Traverse tree nodes in middle order</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) InOrderTraverse() []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.InOrderTraverse()) //2, 4, 5, 6, 7
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_PostOrderTraverse">PostOrderTraverse</span>
|
||||
<p>Traverse tree nodes in post order</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) PostOrderTraverse() []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.PostOrderTraverse()) //5, 2, 4, 7, 6
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_LevelOrderTraverse">LevelOrderTraverse</span>
|
||||
<p>Traverse tree nodes in node level order</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) LevelOrderTraverse() []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.LevelOrderTraverse()) //6, 5, 7, 2, 4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_Depth">Depth</span>
|
||||
<p>Get the depth of a binary saerch tree</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) Depth() int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.Depth()) //4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_HasSubTree">HasSubTree</span>
|
||||
<p>Check if the given tree is sub tree of origin tree or not</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) HasSubTree(subTree *BSTree[T]) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
superTree := tree.NewBSTree(8, &intComparator{})
|
||||
superTree.Insert(4)
|
||||
superTree.Insert(5)
|
||||
superTree.Insert(6)
|
||||
superTree.Insert(9)
|
||||
superTree.Insert(4)
|
||||
|
||||
subTree := tree.NewBSTree(5, &intComparator{})
|
||||
subTree.Insert(4)
|
||||
subTree.Insert(6)
|
||||
|
||||
fmt.Println(superTree.HasSubTree(subTree)) //true
|
||||
fmt.Println(subTree.HasSubTree(superTree)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_Print">Print</span>
|
||||
<p>Print the structure of binary saerch tree</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) Print()
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.Print())
|
||||
// 6
|
||||
// / \
|
||||
// / \
|
||||
// / \
|
||||
// / \
|
||||
// 5 7
|
||||
// /
|
||||
// /
|
||||
// 2
|
||||
// \
|
||||
// 4
|
||||
}
|
||||
```
|
||||
527
docs/datastructure/tree_zh-CN.md
Normal file
527
docs/datastructure/tree_zh-CN.md
Normal file
@@ -0,0 +1,527 @@
|
||||
# Tree
|
||||
树是树节点的集合。 每个树节点都有一个值,一个指向左节点的左指针和一个指向右节点的右指针。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/tree/bstree.go](https://github.com/duke-git/lancet/blob/main/datastructure/tree/bstree.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法
|
||||
```go
|
||||
import (
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
### 1. BSTree
|
||||
|
||||
- [NewBSTree](#NewBSTree)
|
||||
- [Insert](#BSTree_Insert)
|
||||
- [Delete](#BSTree_Delete)
|
||||
- [PreOrderTraverse](#BSTree_PreOrderTraverse)
|
||||
- [InOrderTraverse](#BSTree_InOrderTraverse)
|
||||
- [PostOrderTraverse](#BSTree_PostOrderTraverse)
|
||||
|
||||
- [LevelOrderTraverse](#BSTree_LevelOrderTraverse)
|
||||
- [Depth](#BSTree_Depth)
|
||||
- [HasSubTree](#BSTree_HasSubTree)
|
||||
- [Print](#BSTree_Print)
|
||||
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
## 1. BSTree
|
||||
BSTree是一种二叉搜索树数据结构,其中每个节点有两个孩子,分别称为左孩子和右孩子。 在 BSTree 中:leftNode < rootNode < rightNode。 T类型应该实现lancetconstraints.Comparator。
|
||||
|
||||
### <span id="NewBSTree">NewBSTree</span>
|
||||
<p>返回BSTree指针实例</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func NewBSTree[T any](rootData T, comparator lancetconstraints.Comparator) *BSTree[T]
|
||||
|
||||
type BSTree[T any] struct {
|
||||
root *datastructure.TreeNode[T]
|
||||
comparator lancetconstraints.Comparator
|
||||
}
|
||||
|
||||
type TreeNode[T any] struct {
|
||||
Value T
|
||||
Left *TreeNode[T]
|
||||
Right *TreeNode[T]
|
||||
}
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
fmt.Println(bstree) //
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_Insert">Insert</span>
|
||||
<p>将值插入二叉搜索树</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) Insert(data T)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.PreOrderTraverse()) //6, 5, 2, 4, 7
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_Delete">Delete</span>
|
||||
<p>删除插入二叉搜索树中指定的值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) Delete(data T)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
bstree.Delete(4)
|
||||
|
||||
fmt.Println(bstree.PreOrderTraverse()) //2, 5, 6, 7
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_PreOrderTraverse">PreOrderTraverse</span>
|
||||
<p>按前序遍历树节点</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) PreOrderTraverse() []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.PreOrderTraverse()) //6, 5, 2, 4, 7
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_InOrderTraverse">InOrderTraverse</span>
|
||||
<p>按中序遍历树节点</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) InOrderTraverse() []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.InOrderTraverse()) //2, 4, 5, 6, 7
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_PostOrderTraverse">PostOrderTraverse</span>
|
||||
<p>按后序遍历树节点</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) PostOrderTraverse() []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.PostOrderTraverse()) //5, 2, 4, 7, 6
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_LevelOrderTraverse">LevelOrderTraverse</span>
|
||||
<p>按节点层次遍历树节点</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) LevelOrderTraverse() []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.LevelOrderTraverse()) //6, 5, 7, 2, 4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_Depth">Depth</span>
|
||||
<p>获取树的深度</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) Depth() int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.Depth()) //4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_HasSubTree">HasSubTree</span>
|
||||
<p>判断给定树是否是子树</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) HasSubTree(subTree *BSTree[T]) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
superTree := tree.NewBSTree(8, &intComparator{})
|
||||
superTree.Insert(4)
|
||||
superTree.Insert(5)
|
||||
superTree.Insert(6)
|
||||
superTree.Insert(9)
|
||||
superTree.Insert(4)
|
||||
|
||||
subTree := tree.NewBSTree(5, &intComparator{})
|
||||
subTree.Insert(4)
|
||||
subTree.Insert(6)
|
||||
|
||||
fmt.Println(superTree.HasSubTree(subTree)) //true
|
||||
fmt.Println(subTree.HasSubTree(superTree)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BSTree_Print">Print</span>
|
||||
<p>打印树结构</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *BSTree[T]) Print()
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
bstree := tree.NewBSTree(6, &intComparator{})
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
|
||||
fmt.Println(bstree.Print())
|
||||
// 6
|
||||
// / \
|
||||
// / \
|
||||
// / \
|
||||
// / \
|
||||
// 5 7
|
||||
// /
|
||||
// /
|
||||
// 2
|
||||
// \
|
||||
// 4
|
||||
}
|
||||
```
|
||||
@@ -712,7 +712,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewUnix(unix int64) *theTime
|
||||
```
|
||||
@@ -741,7 +741,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewFormat(t string) (*theTime, error)
|
||||
```
|
||||
@@ -771,7 +771,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewISO8601(iso8601 string) (*theTime, error)
|
||||
```
|
||||
|
||||
@@ -680,7 +680,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewUnixNow() *theTime
|
||||
```
|
||||
@@ -708,7 +708,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewUnix(unix int64) *theTime
|
||||
```
|
||||
@@ -737,7 +737,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewFormat(t string) (*theTime, error)
|
||||
```
|
||||
@@ -767,7 +767,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewISO8601(iso8601 string) (*theTime, error)
|
||||
```
|
||||
|
||||
@@ -21,18 +21,20 @@ import (
|
||||
## Index
|
||||
- [ClearFile](#ClearFile)
|
||||
- [CreateFile](#CreateFile)
|
||||
- [CreateDir](#CreateDir)
|
||||
- [CopyFile](#CopyFile)
|
||||
- [FileMode](#FileMode)
|
||||
- [MiMeType](#MiMeType)
|
||||
- [IsExist](#IsExist)
|
||||
- [IsLink](#IsLink)
|
||||
- [IsDir](#IsDir)
|
||||
|
||||
- [ListFileNames](#ListFileNames)
|
||||
- [RemoveFile](#RemoveFile)
|
||||
- [ReadFileToString](#ReadFileToString)
|
||||
- [ReadFileByLine](#ReadFileByLine)
|
||||
- [Zip](#Zip)
|
||||
|
||||
- [UnZip](#UnZip)
|
||||
- [UnZip](#UnZip)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -92,6 +94,32 @@ func main() {
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="CreateDir">CreateDir</span>
|
||||
<p>Create directory in absolute path. param `absPath` like /a/, /a/b/.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func CreateDir(absPath string) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.CreateDir("/a/")
|
||||
fmt.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="CopyFile">CopyFile</span>
|
||||
<p>Copy src file to dest file. If dest file exist will overwrite it.</p>
|
||||
|
||||
@@ -112,9 +140,9 @@ import (
|
||||
|
||||
func main() {
|
||||
err := fileutil.CopyFile("./test.txt", "./test_copy.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -140,9 +168,9 @@ import (
|
||||
|
||||
func main() {
|
||||
mode, err := fileutil.FileMode("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(mode)
|
||||
}
|
||||
```
|
||||
@@ -310,8 +338,8 @@ import (
|
||||
func main() {
|
||||
err := fileutil.RemoveFile("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -337,12 +365,12 @@ import (
|
||||
|
||||
func main() {
|
||||
path := "./test.txt"
|
||||
fileutil.CreateFile(path)
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
f.WriteString("hello world")
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
f.WriteString("hello world")
|
||||
|
||||
content, _ := fileutil.ReadFileToString(path)
|
||||
content, _ := fileutil.ReadFileToString(path)
|
||||
fmt.Println(content) //hello world
|
||||
}
|
||||
```
|
||||
@@ -370,13 +398,13 @@ import (
|
||||
|
||||
func main() {
|
||||
path := "./text.txt"
|
||||
fileutil.CreateFile(path)
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello\nworld")
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello\nworld")
|
||||
|
||||
contents, _ := fileutil.ReadFileByLine(path)
|
||||
contents, _ := fileutil.ReadFileByLine(path)
|
||||
fmt.Println(contents) //[]string{"hello", "world"}
|
||||
}
|
||||
```
|
||||
@@ -402,7 +430,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.txt", "./test.zip")
|
||||
err := fileutil.Zip("./test.txt", "./test.zip")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
@@ -431,7 +459,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.zip", "./unzip/test.txt")
|
||||
err := fileutil.Zip("./test.zip", "./unzip/test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
## 目录
|
||||
- [ClearFile](#ClearFile)
|
||||
- [CreateFile](#CreateFile)
|
||||
- [CreateDir](#CreateDir)
|
||||
- [CopyFile](#CopyFile)
|
||||
- [FileMode](#FileMode)
|
||||
- [MiMeType](#MiMeType)
|
||||
@@ -92,6 +93,32 @@ func main() {
|
||||
```
|
||||
|
||||
|
||||
### <span id="CreateDir">CreateDir</span>
|
||||
<p>使用绝对路径创建嵌套目录,例如/a/, /a/b/</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CreateDir(absPath string) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.CreateDir("/a/")
|
||||
fmt.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="CopyFile">CopyFile</span>
|
||||
<p>拷贝文件,会覆盖原有的拷贝文件</p>
|
||||
|
||||
@@ -112,9 +139,9 @@ import (
|
||||
|
||||
func main() {
|
||||
err := fileutil.CopyFile("./test.txt", "./test_copy.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -140,9 +167,9 @@ import (
|
||||
|
||||
func main() {
|
||||
mode, err := fileutil.FileMode("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(mode)
|
||||
}
|
||||
```
|
||||
@@ -310,8 +337,8 @@ import (
|
||||
func main() {
|
||||
err := fileutil.RemoveFile("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -337,12 +364,12 @@ import (
|
||||
|
||||
func main() {
|
||||
path := "./test.txt"
|
||||
fileutil.CreateFile(path)
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
f.WriteString("hello world")
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
f.WriteString("hello world")
|
||||
|
||||
content, _ := fileutil.ReadFileToString(path)
|
||||
content, _ := fileutil.ReadFileToString(path)
|
||||
fmt.Println(content) //hello world
|
||||
}
|
||||
```
|
||||
@@ -370,13 +397,13 @@ import (
|
||||
|
||||
func main() {
|
||||
path := "./text.txt"
|
||||
fileutil.CreateFile(path)
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello\nworld")
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello\nworld")
|
||||
|
||||
contents, _ := fileutil.ReadFileByLine(path)
|
||||
contents, _ := fileutil.ReadFileByLine(path)
|
||||
fmt.Println(contents) //[]string{"hello", "world"}
|
||||
}
|
||||
```
|
||||
@@ -402,7 +429,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.txt", "./test.zip")
|
||||
err := fileutil.Zip("./test.txt", "./test.zip")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
@@ -431,7 +458,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.zip", "./unzip/test.txt")
|
||||
err := fileutil.Zip("./test.zip", "./unzip/test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
@@ -101,8 +101,6 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
assert := internal.NewAssert(t, "TestBefore")
|
||||
|
||||
arr := []string{"a", "b", "c", "d", "e"}
|
||||
f := function.Before(3, func(i int) int {
|
||||
return i
|
||||
@@ -120,7 +118,7 @@ func main() {
|
||||
}
|
||||
|
||||
expected := []int64{0, 1, 2, 2, 2}
|
||||
assert.Equal(expected, res)
|
||||
fmt.Println(res) // 0, 1, 2, 2, 2
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -101,8 +101,6 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
assert := internal.NewAssert(t, "TestBefore")
|
||||
|
||||
arr := []string{"a", "b", "c", "d", "e"}
|
||||
f := function.Before(3, func(i int) int {
|
||||
return i
|
||||
@@ -119,8 +117,7 @@ func main() {
|
||||
appendStr(i, arr[i], f)
|
||||
}
|
||||
|
||||
expected := []int64{0, 1, 2, 2, 2}
|
||||
assert.Equal(expected, res)
|
||||
fmt.Println(res) // 0, 1, 2, 2, 2
|
||||
}
|
||||
```
|
||||
|
||||
@@ -297,7 +294,7 @@ func main() {
|
||||
time.Sleep(5 * time.Second)
|
||||
close(stop)
|
||||
|
||||
fmt.Println(res) //[* * * * *]
|
||||
fmt.Println(res) //[* * * * *]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Package maputil includes some functions to manipulate map.
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/maputil/maputil.go](https://github.com/duke-git/lancet/blob/main/maputil/maputil.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/maputil/map.go](https://github.com/duke-git/lancet/blob/main/maputil/map.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
- [Merge](#Merge)
|
||||
- [Minus](#Minus)
|
||||
- [Values](#Values)
|
||||
- [Values](#Values)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -301,4 +302,51 @@ func main() {
|
||||
|
||||
fmt.Println(values) // []string{"a", "a", "b", "c", "d"}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsDisjoint">IsDisjoint</span>
|
||||
<p>Checks two are disjoint if they have no keys in common</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m1 := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
m2 := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
m3 := map[int]string{
|
||||
6: "a",
|
||||
}
|
||||
|
||||
ok := maputil.IsDisjoint(m2, m1)
|
||||
fmt.Println(ok) // false
|
||||
|
||||
ok = maputil.IsDisjoint(m2, m3)
|
||||
fmt.Println(ok) // true
|
||||
}
|
||||
```
|
||||
@@ -5,7 +5,7 @@ maputil包包括一些操作map的函数。
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/maputil/maputil.go](https://github.com/duke-git/lancet/blob/main/maputil/maputil.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/maputil/map.go](https://github.com/duke-git/lancet/blob/main/maputil/map.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
- [Merge](#Merge)
|
||||
- [Minus](#Minus)
|
||||
- [Values](#Values)
|
||||
- [IsDisjoint](#IsDisjoint)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -231,7 +232,6 @@ func main() {
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Minus">Minus</span>
|
||||
<p>返回一个map,其中的key存在于mapA,不存在于mapB.</p>
|
||||
|
||||
@@ -301,4 +301,52 @@ func main() {
|
||||
|
||||
fmt.Println(values) // []string{"a", "a", "b", "c", "d"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="IsDisjoint">IsDisjoint</span>
|
||||
<p>验证两个map是否具有不同的key</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m1 := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
m2 := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
m3 := map[int]string{
|
||||
6: "a",
|
||||
}
|
||||
|
||||
ok := maputil.IsDisjoint(m2, m1)
|
||||
fmt.Println(ok) // false
|
||||
|
||||
ok = maputil.IsDisjoint(m2, m3)
|
||||
fmt.Println(ok) // true
|
||||
}
|
||||
```
|
||||
120
docs/netutil.md
120
docs/netutil.md
@@ -22,16 +22,19 @@ import (
|
||||
|
||||
## Index
|
||||
- [ConvertMapToQueryString](#ConvertMapToQueryString)
|
||||
- [EncodeUrl](#EncodeUrl)
|
||||
|
||||
- [GetInternalIp](#GetInternalIp)
|
||||
- [GetIps](#GetIps)
|
||||
- [GetMacAddrs](#GetMacAddrs)
|
||||
- [GetPublicIpInfo](#GetPublicIpInfo)
|
||||
- [GetRequestPublicIp](#GetRequestPublicIp)
|
||||
- [IsPublicIP](#IsPublicIP)
|
||||
- [IsInternalIP](#IsInternalIP)
|
||||
- [HttpGet](#HttpGet)
|
||||
- [HttpDelete](#HttpDelete)
|
||||
- [HttpPost](#HttpPost)
|
||||
- [HttpPut](#HttpPut)
|
||||
|
||||
- [HttpPatch](#HttpPatch)
|
||||
- [ParseHttpResponse](#ParseHttpResponse)
|
||||
|
||||
@@ -72,6 +75,36 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="EncodeUrl">EncodeUrl</span>
|
||||
<p>Encode url query string values.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func EncodeUrl(urlStr string) (string, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
urlAddr := "http://www.lancet.com?a=1&b=[2]"
|
||||
encodedUrl, err := netutil.EncodeUrl(urlAddr)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(encodedUrl) //http://www.lancet.com?a=1&b=%5B2%5D
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="GetInternalIp">GetInternalIp</span>
|
||||
<p>Get internal ip information.</p>
|
||||
|
||||
@@ -199,8 +232,51 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="GetRequestPublicIp">GetRequestPublicIp</span>
|
||||
<p>Get http request public ip.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetRequestPublicIp(req *http.Request) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ip := "36.112.24.10"
|
||||
|
||||
request1 := http.Request{
|
||||
Method: "GET",
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": {ip},
|
||||
},
|
||||
}
|
||||
publicIp1 := netutil.GetRequestPublicIp(&request1)
|
||||
fmt.Println(publicIp1) //36.112.24.10
|
||||
|
||||
request2 := http.Request{
|
||||
Method: "GET",
|
||||
Header: http.Header{
|
||||
"X-Real-Ip": {ip},
|
||||
},
|
||||
}
|
||||
publicIp2 := netutil.GetRequestPublicIp(&request2)
|
||||
fmt.Println(publicIp2) //36.112.24.10
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsPublicIP">IsPublicIP</span>
|
||||
<p>Checks if a ip is public or not.</p>
|
||||
<p>Checks if an ip is public or not.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -230,6 +306,36 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="IsInternalIP">IsInternalIP</span>
|
||||
<p>Checks if an ip is intranet or not.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsInternalIP(IP net.IP) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ip1 := net.ParseIP("127.0.0.1")
|
||||
ip2 := net.ParseIP("36.112.24.10")
|
||||
|
||||
fmt.Println(netutil.IsInternalIP(ip1)) //true
|
||||
fmt.Println(netutil.IsInternalIP(ip2)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="HttpGet">HttpGet</span>
|
||||
<p>Send http get request.</p>
|
||||
|
||||
@@ -237,7 +343,7 @@ func main() {
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[1] is query param which type should be url.Values or map[string]string,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpGet(url string, params ...any) (*http.Response, error)
|
||||
@@ -279,7 +385,7 @@ func main() {
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[1] is query param which type should be url.Values or map[string]string,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpPost(url string, params ...any) (*http.Response, error)
|
||||
@@ -328,7 +434,7 @@ func main() {
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[1] is query param which type should be url.Values or map[string]string,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpPut(url string, params ...any) (*http.Response, error)
|
||||
@@ -378,7 +484,7 @@ func main() {
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[1] is query param which type should be url.Values or map[string]string,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpDelete(url string, params ...any) (*http.Response, error)
|
||||
@@ -417,7 +523,7 @@ func main() {
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[1] is query param which type should be url.Values or map[string]string,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpPatch(url string, params ...any) (*http.Response, error)
|
||||
|
||||
@@ -21,16 +21,19 @@ import (
|
||||
|
||||
## 目录
|
||||
- [ConvertMapToQueryString](#ConvertMapToQueryString)
|
||||
- [EncodeUrl](#EncodeUrl)
|
||||
- [GetInternalIp](#GetInternalIp)
|
||||
- [GetIps](#GetIps)
|
||||
- [GetMacAddrs](#GetMacAddrs)
|
||||
- [GetPublicIpInfo](#GetPublicIpInfo)
|
||||
- [GetRequestPublicIp](#GetRequestPublicIp)
|
||||
|
||||
- [IsPublicIP](#IsPublicIP)
|
||||
- [IsInternalIP](#IsInternalIP)
|
||||
- [HttpGet](#HttpGet)
|
||||
- [HttpDelete](#HttpDelete)
|
||||
- [HttpPost](#HttpPost)
|
||||
- [HttpPut](#HttpPut)
|
||||
|
||||
- [HttpPatch](#HttpPatch)
|
||||
- [ParseHttpResponse](#ParseHttpResponse)
|
||||
|
||||
@@ -71,6 +74,37 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="EncodeUrl">EncodeUrl</span>
|
||||
<p>编码url query string的值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EncodeUrl(urlStr string) (string, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
urlAddr := "http://www.lancet.com?a=1&b=[2]"
|
||||
encodedUrl, err := netutil.EncodeUrl(urlAddr)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(encodedUrl) //http://www.lancet.com?a=1&b=%5B2%5D
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="GetInternalIp">GetInternalIp</span>
|
||||
<p>获取内部ip</p>
|
||||
|
||||
@@ -197,6 +231,50 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="GetRequestPublicIp">GetRequestPublicIp</span>
|
||||
<p>获取http请求ip</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetRequestPublicIp(req *http.Request) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ip := "36.112.24.10"
|
||||
|
||||
request1 := http.Request{
|
||||
Method: "GET",
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": {ip},
|
||||
},
|
||||
}
|
||||
publicIp1 := netutil.GetRequestPublicIp(&request1)
|
||||
fmt.Println(publicIp1) //36.112.24.10
|
||||
|
||||
request2 := http.Request{
|
||||
Method: "GET",
|
||||
Header: http.Header{
|
||||
"X-Real-Ip": {ip},
|
||||
},
|
||||
}
|
||||
publicIp2 := netutil.GetRequestPublicIp(&request2)
|
||||
fmt.Println(publicIp2) //36.112.24.10
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsPublicIP">IsPublicIP</span>
|
||||
<p>判断ip是否是公共ip</p>
|
||||
|
||||
@@ -227,6 +305,35 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="IsInternalIP">IsInternalIP</span>
|
||||
<p>判断ip是否是局域网ip.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsInternalIP(IP net.IP) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ip1 := net.ParseIP("127.0.0.1")
|
||||
ip2 := net.ParseIP("36.112.24.10")
|
||||
|
||||
fmt.Println(netutil.IsInternalIP(ip1)) //true
|
||||
fmt.Println(netutil.IsInternalIP(ip2)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="HttpGet">HttpGet</span>
|
||||
<p>发送http get请求</p>
|
||||
@@ -235,7 +342,7 @@ func main() {
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]string
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpGet(url string, params ...any) (*http.Response, error)
|
||||
@@ -277,7 +384,7 @@ func main() {
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]string
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpPost(url string, params ...any) (*http.Response, error)
|
||||
@@ -326,7 +433,7 @@ func main() {
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]string
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpPut(url string, params ...any) (*http.Response, error)
|
||||
@@ -376,7 +483,7 @@ func main() {
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]string
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpDelete(url string, params ...any) (*http.Response, error)
|
||||
@@ -415,7 +522,7 @@ func main() {
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]string
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpPatch(url string, params ...any) (*http.Response, error)
|
||||
|
||||
@@ -97,8 +97,8 @@ import (
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
var increaseNumber retry.RetryFunc
|
||||
increaseNumber = func() error {
|
||||
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
@@ -139,6 +139,7 @@ import (
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
|
||||
@@ -99,8 +99,7 @@ import (
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
var increaseNumber retry.RetryFunc
|
||||
increaseNumber = func() error {
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
|
||||
210
docs/slice.md
210
docs/slice.md
@@ -31,10 +31,13 @@ import (
|
||||
- [DifferenceWith](#DifferenceWith)
|
||||
- [DeleteAt](#DeleteAt)
|
||||
- [Drop](#Drop)
|
||||
- [Equal](#Equal)
|
||||
- [EqualWith](#EqualWith)
|
||||
- [Every](#Every)
|
||||
- [Filter](#Filter)
|
||||
- [Find](#Find)
|
||||
- [FindLast](#FindLast)
|
||||
- [Flatten](#Flatten)
|
||||
- [FlattenDeep](#FlattenDeep)
|
||||
- [ForEach](#ForEach)
|
||||
|
||||
@@ -54,7 +57,10 @@ import (
|
||||
- [Some](#Some)
|
||||
- [StringSlice](#StringSlice)
|
||||
- [SymmetricDifference](#SymmetricDifference)
|
||||
- [ToSlice](#ToSlice)
|
||||
- [ToSlicePointer](#ToSlicePointer)
|
||||
- [Unique](#Unique)
|
||||
- [UniqueBy](#UniqueBy)
|
||||
- [Union](#Union)
|
||||
- [UpdateAt](#UpdateAt)
|
||||
- [Without](#Without)
|
||||
@@ -69,7 +75,7 @@ import (
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Contain[T any](slice []T, value T) bool
|
||||
func Contain[T comparable](slice []T, value T) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -92,7 +98,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ContainSubSlice[T any](slice, subslice []T) bool
|
||||
func ContainSubSlice[T comparable](slice, subslice []T) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -250,7 +256,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func DifferenceBy[T any](slice []T, comparedSlice []T, iteratee func(index int, t T) T) []T
|
||||
func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(index int, item T) T) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -360,6 +366,68 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="Equal">Equal</span>
|
||||
<p>Check if two slices are equal: the same length and all elements' order and value are equal.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Equal[T comparable](slice1, slice2 []T) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
slice1 := []int{1, 2, 3}
|
||||
slice2 := []int{1, 2, 3}
|
||||
slice3 := []int{3, 2, 1}
|
||||
|
||||
res1 := slice.Equal(slice1, slice2)
|
||||
res2 := slice.Equal(slice1, slice3)
|
||||
|
||||
fmt.Println(res1) //true
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="EqualWith">EqualWith</span>
|
||||
<p>Check if two slices are equal with comparator func.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func EqualWith[T, U any](slice1 []T, slice2 []U, comparator func(T, U) bool) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
slice1 := []int{1, 2, 3}
|
||||
slice2 := []int{2, 4, 6}
|
||||
|
||||
isDouble := func(a, b int) bool {
|
||||
return b == a*2
|
||||
}
|
||||
|
||||
res := slice.EqualWith(slice1, slice2, isDouble)
|
||||
|
||||
fmt.Println(res) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Every">Every</span>
|
||||
<p>Return true if all of the values in the slice pass the predicate function.</p>
|
||||
@@ -367,7 +435,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Every[T any](slice []T, predicate func(index int, t T) bool) bool
|
||||
func Every[T any](slice []T, predicate func(index int, item T) bool) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -397,7 +465,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Filter[T any](slice []T, predicate func(index int, t T) bool) []T
|
||||
func Filter[T any](slice []T, predicate func(index int, item T) bool) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -426,7 +494,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Find[T any](slice []T, predicate func(index int, t T) bool) (*T, bool)
|
||||
func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -457,7 +525,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func FindLast[T any](slice []T, predicate func(index int, t T) bool) (*T, bool)
|
||||
func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, bool)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -481,6 +549,31 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="Flatten">Flatten</span>
|
||||
<p>Flatten slice with one level.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Flatten(slice any) any
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
arr := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
|
||||
res := slice.Flatten(arr)
|
||||
fmt.Println(res) //{{"a", "b"}, {"c", "d"}}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="FlattenDeep">FlattenDeep</span>
|
||||
<p>flattens slice recursive.</p>
|
||||
|
||||
@@ -500,7 +593,7 @@ import (
|
||||
func main() {
|
||||
arr := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
|
||||
res := slice.FlattenDeep(arr)
|
||||
fmt.Println(res) //[]string{"a", "b", "c", "d"}
|
||||
fmt.Println(res) //{"a", "b", "c", "d"}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -514,7 +607,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ForEach[T any](slice []T, iteratee func(index int, t T))
|
||||
func ForEach[T any](slice []T, iteratee func(index int, item T))
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -543,7 +636,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GroupBy[T any](slice []T, groupFn func(index int, t T) bool) ([]T, []T)
|
||||
func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -654,7 +747,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Intersection[T any](slices ...[]T) []T
|
||||
func Intersection[T comparable](slices ...[]T) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -712,7 +805,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IndexOf[T any](slice []T, value T) int
|
||||
func IndexOf[T comparable](slice []T, value T) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -740,7 +833,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func LastIndexOf[T any](slice []T, value T) int
|
||||
func LastIndexOf[T comparable](slice []T, value T) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -769,7 +862,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Map[T any, U any](slice []T, iteratee func(index int, t T) U) []U
|
||||
func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -823,7 +916,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Reduce[T any](slice []T, iteratee func(index int, t1, t2 T) T, initial T) T
|
||||
func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initial T) T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -920,7 +1013,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Some[T any](slice []T, predicate func(index int, t T) bool) bool
|
||||
func Some[T any](slice []T, predicate func(index int, item T) bool) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -975,7 +1068,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func SymmetricDifference[T any](slices ...[]T) []T
|
||||
func SymmetricDifference[T comparable](slices ...[]T) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -998,13 +1091,62 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="ToSlice">ToSlice</span>
|
||||
<p>Returns a slices of a variable parameter transformation</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToSlice[T any](value ...T) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res := slice.ToSlice("a", "b")
|
||||
fmt.Println(res) //{"a", "b"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToSlicePointer">ToSlicePointer</span>
|
||||
<p>Returns a pointer to the slices of a variable parameter transformation</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToSlicePointer[T any](value ...T) []*T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str1 := "a"
|
||||
str2 := "b"
|
||||
res := slice.ToSlicePointer(str1, str2)
|
||||
fmt.Println(res) // res -> []*string{&str1, &str2}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Unique">Unique</span>
|
||||
<p>Remove duplicate elements in slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Unique[T any](slice []T) []T
|
||||
func Unique[T comparable](slice []T) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -1022,13 +1164,39 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="Union">Unique</span>
|
||||
### <span id="UniqueBy">UniqueBy</span>
|
||||
<p>Call iteratee func with every item of slice, then remove duplicated.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res := slice.UniqueBy([]int{1, 2, 3, 4, 5, 6}, func(val int) int {
|
||||
return val % 4
|
||||
})
|
||||
fmt.Println(res) //[]int{1, 2, 3, 0}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Union">Union</span>
|
||||
<p>Creates a slice of unique values, in order, from all given slices. using == for equality comparisons.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Union[T any](slices ...[]T) []T
|
||||
func Union[T comparable](slices ...[]T) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -1082,7 +1250,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Without[T any](slice []T, values ...T) []T
|
||||
func Without[T comparable](slice []T, values ...T) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
|
||||
@@ -32,9 +32,12 @@ import (
|
||||
- [DeleteAt](#DeleteAt)
|
||||
- [Drop](#Drop)
|
||||
- [Every](#Every)
|
||||
- [Equal](#Equal)
|
||||
- [EqualWith](#EqualWith)
|
||||
- [Filter](#Filter)
|
||||
- [Find](#Find)
|
||||
- [FindLast](#FindLast)
|
||||
- [Flatten](#Flatten)
|
||||
- [FlattenDeep](#FlattenDeep)
|
||||
- [ForEach](#ForEach)
|
||||
|
||||
@@ -54,7 +57,10 @@ import (
|
||||
- [Some](#Some)
|
||||
- [StringSlice](#StringSlice)
|
||||
- [SymmetricDifference](#SymmetricDifference)
|
||||
- [ToSlice](#ToSlice)
|
||||
- [ToSlicePointer](#ToSlicePointer)
|
||||
- [Unique](#Unique)
|
||||
- [UniqueBy](#UniqueBy)
|
||||
- [Union](#Union)
|
||||
- [UpdateAt](#UpdateAt)
|
||||
- [Without](#Without)
|
||||
@@ -69,7 +75,7 @@ import (
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Contain[T any](slice []T, value T) bool
|
||||
func Contain[T comparable](slice []T, value T) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -92,7 +98,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ContainSubSlice[T any](slice, subslice []T) bool
|
||||
func ContainSubSlice[T comparable](slice, subslice []T) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -250,7 +256,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func DifferenceBy[T any](slice []T, comparedSlice []T, iteratee func(index int, t T) T) []T
|
||||
func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(index int, item T) T) []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -369,7 +375,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Every[T any](slice []T, predicate func(index int, t T) bool) bool
|
||||
func Every[T any](slice []T, predicate func(index int, item T) bool) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -393,13 +399,76 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="Filter">Filter</span>
|
||||
<p>返回与函数匹配的所有元素。 函数签名应该是 func(index int, value any) bool</p>
|
||||
### <span id="Equal">Equal</span>
|
||||
<p>检查两个切片是否相等,相等条件:切片长度相同,元素顺序和值都相同</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Filter[T any](slice []T, predicate func(index int, t T) bool) []T
|
||||
func Equal[T comparable](slice1, slice2 []T) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
slice1 := []int{1, 2, 3}
|
||||
slice2 := []int{1, 2, 3}
|
||||
slice3 := []int{3, 2, 1}
|
||||
|
||||
res1 := slice.Equal(slice1, slice2)
|
||||
res2 := slice.Equal(slice1, slice3)
|
||||
|
||||
fmt.Println(res1) //true
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="EqualWith">EqualWith</span>
|
||||
<p>检查两个切片是否相等,相等条件:对两个切片的元素调用比较函数comparator,返回true</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EqualWith[T, U any](slice1 []T, slice2 []U, comparator func(T, U) bool) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
slice1 := []int{1, 2, 3}
|
||||
slice2 := []int{2, 4, 6}
|
||||
|
||||
isDouble := func(a, b int) bool {
|
||||
return b == a*2
|
||||
}
|
||||
|
||||
res := slice.EqualWith(slice1, slice2, isDouble)
|
||||
|
||||
fmt.Println(res) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Filter">Filter</span>
|
||||
<p>返回切片中通过predicate函数真值测试的所有元素</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Filter[T any](slice []T, predicate func(index int, item T) bool) []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -423,12 +492,12 @@ func main() {
|
||||
|
||||
|
||||
### <span id="Find">Find</span>
|
||||
<p>遍历slice的元素,返回第一个通过function真值测试的元素</p>
|
||||
<p>遍历切片的元素,返回第一个通过predicate函数真值测试的元素</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Find[T any](slice []T, predicate func(index int, t T) bool) (*T, bool)
|
||||
func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -454,12 +523,12 @@ func main() {
|
||||
|
||||
|
||||
### <span id="FindLast">FindLast</span>
|
||||
<p>从头到尾遍历 slice 的元素,返回最后一个通过函数真值测试的元素。</p>
|
||||
<p>从头到尾遍历slice的元素,返回最后一个通过predicate函数真值测试的元素。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FindLast[T any](slice []T, predicate func(index int, t T) bool) (*T, bool)
|
||||
func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, bool)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -482,6 +551,30 @@ func main() {
|
||||
```
|
||||
|
||||
|
||||
### <span id="Flatten">Flatten</span>
|
||||
<p>将切片压平一层</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Flatten(slice any) any
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
arr := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
|
||||
res := slice.Flatten(arr)
|
||||
fmt.Println(res) //{{"a", "b"}, {"c", "d"}}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="FlattenDeep">FlattenDeep</span>
|
||||
<p>flattens slice recursive.</p>
|
||||
@@ -511,12 +604,12 @@ func main() {
|
||||
|
||||
|
||||
### <span id="ForEach">ForEach</span>
|
||||
<p>遍历slice的元素并为每个元素调用函数</p>
|
||||
<p>遍历切片的元素并为每个元素调用iteratee函数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ForEach[T any](slice []T, iteratee func(index int, t T))
|
||||
func ForEach[T any](slice []T, iteratee func(index int, item T))
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -545,7 +638,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GroupBy[T any](slice []T, groupFn func(index int, t T) bool) ([]T, []T)
|
||||
func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -654,7 +747,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Intersection[T any](slices ...[]T) []T
|
||||
func Intersection[T comparable](slices ...[]T) []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -712,7 +805,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IndexOf[T any](slice []T, value T) int
|
||||
func IndexOf[T comparable](slice []T, value T) int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -740,7 +833,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func LastIndexOf[T any](slice []T, value T) int
|
||||
func LastIndexOf[T comparable](slice []T, value T) int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -768,7 +861,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Map[T any, U any](slice []T, iteratee func(index int, t T) U) []U
|
||||
func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -817,12 +910,12 @@ func main() {
|
||||
|
||||
|
||||
### <span id="Reduce">Reduce</span>
|
||||
<p>将slice中的元素依次运行函数,返回运行结果</p>
|
||||
<p>将切片中的元素依次运行iteratee函数,返回运行结果</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Reduce[T any](slice []T, iteratee func(index int, t1, t2 T) T, initial T) T
|
||||
func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initial T) T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -919,7 +1012,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Some[T any](slice []T, predicate func(index int, t T) bool) bool
|
||||
func Some[T any](slice []T, predicate func(index int, item T) bool) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -974,7 +1067,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func SymmetricDifference[T any](slices ...[]T) []T
|
||||
func SymmetricDifference[T comparable](slices ...[]T) []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -996,13 +1089,63 @@ func main() {
|
||||
```
|
||||
|
||||
|
||||
### <span id="ToSlice">ToSlice</span>
|
||||
<p>将可变参数转为切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToSlice[T any](value ...T) []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res := slice.ToSlice("a", "b")
|
||||
fmt.Println(res) //{"a", "b"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToSlicePointer">ToSlicePointer</span>
|
||||
<p>将可变参数转为指针切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToSlicePointer[T any](value ...T) []*T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str1 := "a"
|
||||
str2 := "b"
|
||||
res := slice.ToSlicePointer(str1, str2)
|
||||
fmt.Println(res) // res -> []*string{&str1, &str2}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Unique">Unique</span>
|
||||
<p>删除切片中的重复元素</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Unique[T any](slice []T) []T
|
||||
func Unique[T comparable](slice []T) []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -1020,13 +1163,39 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="Union">Unique</span>
|
||||
<p>从所有给定的切片按顺序创建一个唯一值切片。 使用 == 进行相等比较。</p>
|
||||
### <span id="UniqueBy">UniqueBy</span>
|
||||
<p>对切片的每个元素调用iteratee函数,然后删除重复元素</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Union[T any](slices ...[]T) []T
|
||||
func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res := slice.UniqueBy([]int{1, 2, 3, 4, 5, 6}, func(val int) int {
|
||||
return val % 4
|
||||
})
|
||||
fmt.Println(res) //[]int{1, 2, 3, 0}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Union">Union</span>
|
||||
<p>从所有给定的切片按顺序创建一个唯一值切片,使用==进行相等比较</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Union[T comparable](slices ...[]T) []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -1048,7 +1217,7 @@ func main() {
|
||||
|
||||
|
||||
### <span id="UpdateAt">UpdateAt</span>
|
||||
<p>更新索引处的切片元素。 如果 param index < 0 或 index >= len(slice),将返回错误</p>
|
||||
<p>更新索引处的切片元素。 如果index < 0或 index >= len(slice),将返回错误</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -1080,7 +1249,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Without[T any](slice []T, values ...T) []T
|
||||
func Without[T comparable](slice []T, values ...T) []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
- [RemoveOsEnv](#RemoveOsEnv)
|
||||
- [CompareOsEnv](#CompareOsEnv)
|
||||
- [ExecCommand](#ExecCommand)
|
||||
- [GetOsBits](#GetOsBits)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -210,7 +211,7 @@ func main() {
|
||||
|
||||
|
||||
### <span id="ExecCommand">CompareOsEnv</span>
|
||||
<p>use shell /bin/bash -c(linux) or cmd (windows) to execute command.</p>
|
||||
<p>Use shell /bin/bash -c(linux) or cmd (windows) to execute command.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -236,7 +237,27 @@ func main() {
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="GetOsBits">GetOsBits</span>
|
||||
<p>Get current os bits, 32bit or 64bit. return 32 or 64</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetOsBits() int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
osBit := system.GetOsBits()
|
||||
fmt.Println(osBit)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -26,8 +26,10 @@ import (
|
||||
- [GetOsEnv](#GetOsEnv)
|
||||
- [SetOsEnv](#SetOsEnv)
|
||||
- [RemoveOsEnv](#RemoveOsEnv)
|
||||
|
||||
- [CompareOsEnv](#CompareOsEnv)
|
||||
- [ExecCommand](#ExecCommand)
|
||||
- [GetOsBits](#GetOsBits)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -236,6 +238,30 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="GetOsBits">GetOsBits</span>
|
||||
<p>获取当前操作系统位数,返回32或64</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetOsBits() int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
osBit := system.GetOsBits()
|
||||
fmt.Println(osBit)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
@@ -40,6 +41,11 @@ func CreateFile(path string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// CreateDir create directory in absolute path. param `absPath` like /a/, /a/b/
|
||||
func CreateDir(absPath string) error {
|
||||
return os.MkdirAll(path.Dir(absPath), os.ModePerm)
|
||||
}
|
||||
|
||||
// IsDir checks if the path is directory or not
|
||||
func IsDir(path string) bool {
|
||||
file, err := os.Stat(path)
|
||||
@@ -110,7 +116,7 @@ func ReadFileByLine(path string) ([]string, error) {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
res := make([]string, 0)
|
||||
result := make([]string, 0)
|
||||
buf := bufio.NewReader(f)
|
||||
|
||||
for {
|
||||
@@ -122,10 +128,10 @@ func ReadFileByLine(path string) ([]string, error) {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
res = append(res, l)
|
||||
result = append(result, l)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ListFileNames return all file names in the path
|
||||
@@ -144,14 +150,14 @@ func ListFileNames(path string) ([]string, error) {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
res := []string{}
|
||||
result := []string{}
|
||||
for i := 0; i < sz; i++ {
|
||||
if !fs[i].IsDir() {
|
||||
res = append(res, fs[i].Name())
|
||||
result = append(result, fs[i].Name())
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Zip create zip file, fpath could be a single file or a directory
|
||||
|
||||
@@ -25,6 +25,7 @@ func TestCreateFile(t *testing.T) {
|
||||
f := "./text.txt"
|
||||
if CreateFile(f) {
|
||||
file, err := os.Open(f)
|
||||
defer file.Close()
|
||||
assert.IsNil(err)
|
||||
assert.Equal(f, file.Name())
|
||||
} else {
|
||||
@@ -33,6 +34,27 @@ func TestCreateFile(t *testing.T) {
|
||||
os.Remove(f)
|
||||
}
|
||||
|
||||
func TestCreateDir(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCreateDir")
|
||||
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
dirPath := pwd + "/a/"
|
||||
err = CreateDir(dirPath)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.Equal(true, IsExist(dirPath))
|
||||
os.Remove(dirPath)
|
||||
assert.Equal(false, IsExist(dirPath))
|
||||
}
|
||||
|
||||
func TestIsDir(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsDir")
|
||||
|
||||
@@ -90,6 +112,7 @@ func TestReadFileToString(t *testing.T) {
|
||||
CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello world")
|
||||
|
||||
content, _ := ReadFileToString(path)
|
||||
@@ -197,6 +220,7 @@ func TestMiMeType(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMiMeType")
|
||||
|
||||
f, _ := os.Open("./file.go")
|
||||
defer f.Close()
|
||||
assert.Equal("text/plain; charset=utf-8", MiMeType(f))
|
||||
assert.Equal("text/plain; charset=utf-8", MiMeType("./file.go"))
|
||||
}
|
||||
|
||||
@@ -27,16 +27,16 @@ func After(n int, fn any) func(args ...any) []reflect.Value {
|
||||
func Before(n int, fn any) func(args ...any) []reflect.Value {
|
||||
// Catch programming error while constructing the closure
|
||||
mustBeFunction(fn)
|
||||
var res []reflect.Value
|
||||
var result []reflect.Value
|
||||
return func(args ...any) []reflect.Value {
|
||||
if n > 0 {
|
||||
res = unsafeInvokeFunc(fn, args...)
|
||||
result = unsafeInvokeFunc(fn, args...)
|
||||
}
|
||||
if n <= 0 {
|
||||
fn = nil
|
||||
}
|
||||
n--
|
||||
return res
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BIN
logo.png
BIN
logo.png
Binary file not shown.
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 18 KiB |
@@ -8,10 +8,12 @@ import "reflect"
|
||||
|
||||
// Keys returns a slice of the map's keys
|
||||
func Keys[K comparable, V any](m map[K]V) []K {
|
||||
keys := make([]K, 0, len(m))
|
||||
keys := make([]K, len(m))
|
||||
|
||||
var i int
|
||||
for k := range m {
|
||||
keys = append(keys, k)
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
|
||||
return keys
|
||||
@@ -19,10 +21,12 @@ func Keys[K comparable, V any](m map[K]V) []K {
|
||||
|
||||
// Values returns a slice of the map's values
|
||||
func Values[K comparable, V any](m map[K]V) []V {
|
||||
values := make([]V, 0, len(m))
|
||||
values := make([]V, len(m))
|
||||
|
||||
var i int
|
||||
for _, v := range m {
|
||||
values = append(values, v)
|
||||
values[i] = v
|
||||
i++
|
||||
}
|
||||
|
||||
return values
|
||||
@@ -30,15 +34,15 @@ func Values[K comparable, V any](m map[K]V) []V {
|
||||
|
||||
// Merge maps, next key will overwrite previous key
|
||||
func Merge[K comparable, V any](maps ...map[K]V) map[K]V {
|
||||
res := make(map[K]V, 0)
|
||||
result := make(map[K]V, 0)
|
||||
|
||||
for _, m := range maps {
|
||||
for k, v := range m {
|
||||
res[k] = v
|
||||
result[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// ForEach executes iteratee funcation for every key and value pair in map
|
||||
@@ -50,14 +54,14 @@ func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V)) {
|
||||
|
||||
// Filter iterates over map, return a new map contains all key and value pairs pass the predicate function
|
||||
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V {
|
||||
res := make(map[K]V)
|
||||
result := make(map[K]V)
|
||||
|
||||
for k, v := range m {
|
||||
if predicate(k, v) {
|
||||
res[k] = v
|
||||
result[k] = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Intersect iterates over maps, return a new map of key and value pairs in all given maps
|
||||
@@ -69,7 +73,7 @@ func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
|
||||
return maps[0]
|
||||
}
|
||||
|
||||
var res map[K]V
|
||||
var result map[K]V
|
||||
|
||||
reducer := func(m1, m2 map[K]V) map[K]V {
|
||||
m := make(map[K]V)
|
||||
@@ -82,25 +86,35 @@ func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
|
||||
}
|
||||
|
||||
reduceMaps := make([]map[K]V, 2, 2)
|
||||
res = reducer(maps[0], maps[1])
|
||||
result = reducer(maps[0], maps[1])
|
||||
|
||||
for i := 2; i < len(maps); i++ {
|
||||
reduceMaps[0] = res
|
||||
reduceMaps[0] = result
|
||||
reduceMaps[1] = maps[i]
|
||||
res = reducer(reduceMaps[0], reduceMaps[1])
|
||||
result = reducer(reduceMaps[0], reduceMaps[1])
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Minus creates an map of whose key in mapA but not in mapB
|
||||
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V {
|
||||
res := make(map[K]V)
|
||||
result := make(map[K]V)
|
||||
|
||||
for k, v := range mapA {
|
||||
if _, ok := mapB[k]; !ok {
|
||||
res[k] = v
|
||||
result[k] = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// IsDisjoint two map are disjoint if they have no keys in common
|
||||
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool {
|
||||
for k := range mapA {
|
||||
if _, ok := mapB[k]; ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -148,3 +148,25 @@ func TestMinus(t *testing.T) {
|
||||
|
||||
assert.Equal(map[string]int{"c": 3}, Minus(m1, m2))
|
||||
}
|
||||
|
||||
func TestIsDisjoint(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMinus")
|
||||
|
||||
m1 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
}
|
||||
|
||||
m2 := map[string]int{
|
||||
"d": 22,
|
||||
}
|
||||
|
||||
assert.Equal(true, IsDisjoint(m1, m2))
|
||||
|
||||
m3 := map[string]int{
|
||||
"a": 22,
|
||||
}
|
||||
|
||||
assert.Equal(false, IsDisjoint(m1, m3))
|
||||
}
|
||||
|
||||
@@ -57,9 +57,9 @@ func Percent(val, total float64, n int) float64 {
|
||||
return float64(0)
|
||||
}
|
||||
tmp := val / total * 100
|
||||
res := RoundToFloat(tmp, n)
|
||||
result := RoundToFloat(tmp, n)
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// RoundToString round up to n decimal places
|
||||
@@ -67,8 +67,8 @@ func RoundToString(x float64, n int) string {
|
||||
tmp := math.Pow(10.0, float64(n))
|
||||
x *= tmp
|
||||
x = math.Round(x)
|
||||
res := strconv.FormatFloat(x/tmp, 'f', n, 64)
|
||||
return res
|
||||
result := strconv.FormatFloat(x/tmp, 'f', n, 64)
|
||||
return result
|
||||
}
|
||||
|
||||
// RoundToFloat round up to n decimal places
|
||||
@@ -89,8 +89,8 @@ func TruncRound(x float64, n int) float64 {
|
||||
} else {
|
||||
newFloat = temp[0] + "." + temp[1][:n]
|
||||
}
|
||||
res, _ := strconv.ParseFloat(newFloat, 64)
|
||||
return res
|
||||
result, _ := strconv.ParseFloat(newFloat, 64)
|
||||
return result
|
||||
}
|
||||
|
||||
// Max return max value of params
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
// HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `url` is required.
|
||||
// HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `params` is variable, the order is:
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any, when content-type header is
|
||||
// multipart/form-data or application/x-www-form-urlencoded, params[1] should be url.Values
|
||||
// params[1] is query string param which type should be url.Values or map[string]string, when content-type header is
|
||||
// multipart/form-data or application/x-www-form-urlencoded
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
package netutil
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
@@ -57,9 +56,13 @@ func TestHttpPostFormData(t *testing.T) {
|
||||
UserId int `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "TestAddToDo")
|
||||
// postData := url.Values{}
|
||||
// postData.Add("userId", "1")
|
||||
// postData.Add("title", "TestAddToDo")
|
||||
|
||||
postData := make(map[string]string)
|
||||
postData["userId"] = "1"
|
||||
postData["title"] = "title"
|
||||
|
||||
resp, err := HttpPost(apiUrl, header, postData, nil)
|
||||
if err != nil {
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GetInternalIp return internal ipv4
|
||||
@@ -24,6 +26,26 @@ func GetInternalIp() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetRequestPublicIp return the requested public ip
|
||||
func GetRequestPublicIp(req *http.Request) string {
|
||||
var ip string
|
||||
for _, ip = range strings.Split(req.Header.Get("X-Forwarded-For"), ",") {
|
||||
if ip = strings.TrimSpace(ip); ip != "" && !IsInternalIP(net.ParseIP(ip)) {
|
||||
return ip
|
||||
}
|
||||
}
|
||||
|
||||
if ip = strings.TrimSpace(req.Header.Get("X-Real-Ip")); ip != "" && !IsInternalIP(net.ParseIP(ip)) {
|
||||
return ip
|
||||
}
|
||||
|
||||
if ip, _, _ = net.SplitHostPort(req.RemoteAddr); !IsInternalIP(net.ParseIP(ip)) {
|
||||
return ip
|
||||
}
|
||||
|
||||
return ip
|
||||
}
|
||||
|
||||
// GetPublicIpInfo return public ip information
|
||||
// return the PublicIpInfo struct
|
||||
func GetPublicIpInfo() (*PublicIpInfo, error) {
|
||||
@@ -122,3 +144,29 @@ func IsPublicIP(IP net.IP) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsInternalIP verify an ip is intranet or not
|
||||
func IsInternalIP(IP net.IP) bool {
|
||||
if IP.IsLoopback() {
|
||||
return true
|
||||
}
|
||||
if ip4 := IP.To4(); ip4 != nil {
|
||||
return ip4[0] == 10 ||
|
||||
(ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31) ||
|
||||
(ip4[0] == 169 && ip4[1] == 254) ||
|
||||
(ip4[0] == 192 && ip4[1] == 168)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// EncodeUrl encode url
|
||||
func EncodeUrl(urlStr string) (string, error) {
|
||||
URL, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
URL.RawQuery = URL.Query().Encode()
|
||||
|
||||
return URL.String(), nil
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package netutil
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -81,9 +80,18 @@ func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryPar
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if req.Header.Get("Content-Type") == "multipart/form-data" || req.Header.Get("Content-Type") == "application/x-www-form-urlencoded" {
|
||||
formData := queryParam.(url.Values)
|
||||
err = setBodyByte(req, []byte(formData.Encode()))
|
||||
if strings.Contains(req.Header.Get("Content-Type"), "multipart/form-data") || req.Header.Get("Content-Type") == "application/x-www-form-urlencoded" {
|
||||
if formData, ok := queryParam.(url.Values); ok {
|
||||
err = setBodyByte(req, []byte(formData.Encode()))
|
||||
}
|
||||
if formData, ok := queryParam.(map[string]string); ok {
|
||||
postData := url.Values{}
|
||||
for k, v := range formData {
|
||||
postData.Set(k, v)
|
||||
}
|
||||
err = setBodyByte(req, []byte(postData.Encode()))
|
||||
}
|
||||
|
||||
} else {
|
||||
err = setBodyByte(req, body)
|
||||
}
|
||||
@@ -132,15 +140,15 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam any) error {
|
||||
var values url.Values
|
||||
if queryParam != nil {
|
||||
switch v := queryParam.(type) {
|
||||
case map[string]any:
|
||||
case map[string]string:
|
||||
values = url.Values{}
|
||||
for k := range v {
|
||||
values.Set(k, fmt.Sprintf("%v", v[k]))
|
||||
values.Set(k, v[k])
|
||||
}
|
||||
case url.Values:
|
||||
values = v
|
||||
default:
|
||||
return errors.New("query params type should be url.Values or map[string]any")
|
||||
return errors.New("query string params type should be url.Values or map[string]string")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package netutil
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
@@ -15,6 +16,30 @@ func TestGetInternalIp(t *testing.T) {
|
||||
assert.IsNotNil(ip)
|
||||
}
|
||||
|
||||
func TestGetRequestPublicIp(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestGetPublicIpInfo")
|
||||
|
||||
ip := "36.112.24.10"
|
||||
|
||||
request := http.Request{
|
||||
Method: "GET",
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": {ip},
|
||||
},
|
||||
}
|
||||
publicIp := GetRequestPublicIp(&request)
|
||||
assert.Equal(publicIp, ip)
|
||||
|
||||
request = http.Request{
|
||||
Method: "GET",
|
||||
Header: http.Header{
|
||||
"X-Real-Ip": {ip},
|
||||
},
|
||||
}
|
||||
publicIp = GetRequestPublicIp(&request)
|
||||
assert.Equal(publicIp, ip)
|
||||
}
|
||||
|
||||
func TestGetPublicIpInfo(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestGetPublicIpInfo")
|
||||
|
||||
@@ -43,6 +68,25 @@ func TestIsPublicIP(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsInternalIP(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsInternalIP")
|
||||
|
||||
ips := []net.IP{
|
||||
net.ParseIP("127.0.0.1"),
|
||||
net.ParseIP("192.168.0.1"),
|
||||
net.ParseIP("10.91.210.131"),
|
||||
net.ParseIP("172.20.16.1"),
|
||||
net.ParseIP("36.112.24.10"),
|
||||
}
|
||||
|
||||
expected := []bool{true, true, true, true, false}
|
||||
|
||||
for i := 0; i < len(ips); i++ {
|
||||
actual := IsInternalIP(ips[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetIps(t *testing.T) {
|
||||
ips := GetIps()
|
||||
t.Log(ips)
|
||||
@@ -52,3 +96,16 @@ func TestGetMacAddrs(t *testing.T) {
|
||||
macAddrs := GetMacAddrs()
|
||||
t.Log(macAddrs)
|
||||
}
|
||||
|
||||
func TestEncodeUrl(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsInternalIP")
|
||||
|
||||
urlAddr := "http://www.lancet.com?a=1&b=[2]"
|
||||
encodedUrl, err := EncodeUrl(urlAddr)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
|
||||
expected := "http://www.lancet.com?a=1&b=%5B2%5D"
|
||||
assert.Equal(expected, encodedUrl)
|
||||
}
|
||||
|
||||
280
slice/slice.go
280
slice/slice.go
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights resulterved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package slice implements some functions to manipulate slice.
|
||||
@@ -13,9 +13,9 @@ import (
|
||||
)
|
||||
|
||||
// Contain check if the value is in the slice or not
|
||||
func Contain[T any](slice []T, value T) bool {
|
||||
func Contain[T comparable](slice []T, value T) bool {
|
||||
for _, v := range slice {
|
||||
if reflect.DeepEqual(v, value) {
|
||||
if v == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ func Contain[T any](slice []T, value T) bool {
|
||||
}
|
||||
|
||||
// ContainSubSlice check if the slice contain subslice or not
|
||||
func ContainSubSlice[T any](slice, subslice []T) bool {
|
||||
func ContainSubSlice[T comparable](slice, subslice []T) bool {
|
||||
for _, v := range subslice {
|
||||
if !Contain(slice, v) {
|
||||
return false
|
||||
@@ -36,10 +36,10 @@ func ContainSubSlice[T any](slice, subslice []T) bool {
|
||||
|
||||
// Chunk creates an slice of elements split into groups the length of size.
|
||||
func Chunk[T any](slice []T, size int) [][]T {
|
||||
var res [][]T
|
||||
var result [][]T
|
||||
|
||||
if len(slice) == 0 || size <= 0 {
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
length := len(slice)
|
||||
@@ -47,9 +47,9 @@ func Chunk[T any](slice []T, size int) [][]T {
|
||||
for _, v := range slice {
|
||||
var tmp []T
|
||||
tmp = append(tmp, v)
|
||||
res = append(res, tmp)
|
||||
result = append(result, tmp)
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// divide slice equally
|
||||
@@ -57,74 +57,74 @@ func Chunk[T any](slice []T, size int) [][]T {
|
||||
for i := 0; i < divideNum; i++ {
|
||||
if i == divideNum-1 {
|
||||
if len(slice[i*size:]) > 0 {
|
||||
res = append(res, slice[i*size:])
|
||||
result = append(result, slice[i*size:])
|
||||
}
|
||||
} else {
|
||||
res = append(res, slice[i*size:(i+1)*size])
|
||||
result = append(result, slice[i*size:(i+1)*size])
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Compact creates an slice with all falsey values removed. The values false, nil, 0, and "" are falsey
|
||||
func Compact[T any](slice []T) []T {
|
||||
res := make([]T, 0, 0)
|
||||
result := make([]T, 0, 0)
|
||||
for _, v := range slice {
|
||||
if !reflect.DeepEqual(v, nil) &&
|
||||
!reflect.DeepEqual(v, false) &&
|
||||
!reflect.DeepEqual(v, "") &&
|
||||
!reflect.DeepEqual(v, 0) {
|
||||
res = append(res, v)
|
||||
result = append(result, v)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Concat creates a new slice concatenating slice with any additional slices and/or values.
|
||||
func Concat[T any](slice []T, values ...[]T) []T {
|
||||
res := append([]T{}, slice...)
|
||||
result := append([]T{}, slice...)
|
||||
|
||||
for _, v := range values {
|
||||
res = append(res, v...)
|
||||
result = append(result, v...)
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Difference creates an slice of whose element in slice but not in comparedSlice
|
||||
func Difference[T comparable](slice, comparedSlice []T) []T {
|
||||
var res []T
|
||||
var result []T
|
||||
for _, v := range slice {
|
||||
if !Contain(comparedSlice, v) {
|
||||
res = append(res, v)
|
||||
result = append(result, v)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// DifferenceBy it accepts iteratee which is invoked for each element of slice
|
||||
// and values to generate the criterion by which they're compared.
|
||||
// like lodash.js differenceBy: https://lodash.com/docs/4.17.15#differenceBy,
|
||||
func DifferenceBy[T any](slice []T, comparedSlice []T, iteratee func(index int, t T) T) []T {
|
||||
func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(index int, item T) T) []T {
|
||||
orginSliceAfterMap := Map(slice, iteratee)
|
||||
comparedSliceAfterMap := Map(comparedSlice, iteratee)
|
||||
|
||||
res := make([]T, 0, 0)
|
||||
result := make([]T, 0, 0)
|
||||
for i, v := range orginSliceAfterMap {
|
||||
if !Contain(comparedSliceAfterMap, v) {
|
||||
res = append(res, slice[i])
|
||||
result = append(result, slice[i])
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
//DifferenceWith accepts comparator which is invoked to compare elements of slice to values. The order and references of result values are determined by the first slice. The comparator is invoked with two arguments: (arrVal, othVal).
|
||||
func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value, otherValue T) bool) []T {
|
||||
res := make([]T, 0, 0)
|
||||
result := make([]T, 0, 0)
|
||||
|
||||
getIndex := func(arr []T, item T, comparison func(v1, v2 T) bool) int {
|
||||
index := -1
|
||||
@@ -140,15 +140,46 @@ func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value,
|
||||
for i, v := range slice {
|
||||
index := getIndex(comparedSlice, v, comparator)
|
||||
if index == -1 {
|
||||
res = append(res, slice[i])
|
||||
result = append(result, slice[i])
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Equal checks if two slices are equal: the same length and all elements' order and value are equal
|
||||
func Equal[T comparable](slice1, slice2 []T) bool {
|
||||
if len(slice1) != len(slice2) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range slice1 {
|
||||
if slice1[i] != slice2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// EqualWith checks if two slices are equal with comparator func
|
||||
func EqualWith[T, U any](slice1 []T, slice2 []U, comparator func(T, U) bool) bool {
|
||||
if len(slice1) != len(slice2) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, v1 := range slice1 {
|
||||
v2 := slice2[i]
|
||||
if !comparator(v1, v2) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Every return true if all of the values in the slice pass the predicate function.
|
||||
func Every[T any](slice []T, predicate func(index int, t T) bool) bool {
|
||||
func Every[T any](slice []T, predicate func(index int, item T) bool) bool {
|
||||
if predicate == nil {
|
||||
panic("predicate func is missing")
|
||||
}
|
||||
@@ -164,7 +195,7 @@ func Every[T any](slice []T, predicate func(index int, t T) bool) bool {
|
||||
}
|
||||
|
||||
// None return true if all the values in the slice mismatch the criteria
|
||||
func None[T any](slice []T, predicate func(index int, t T) bool) bool {
|
||||
func None[T any](slice []T, predicate func(index int, item T) bool) bool {
|
||||
if predicate == nil {
|
||||
panic("predicate func is missing")
|
||||
}
|
||||
@@ -180,7 +211,7 @@ func None[T any](slice []T, predicate func(index int, t T) bool) bool {
|
||||
}
|
||||
|
||||
// Some return true if any of the values in the list pass the predicate function.
|
||||
func Some[T any](slice []T, predicate func(index int, t T) bool) bool {
|
||||
func Some[T any](slice []T, predicate func(index int, item T) bool) bool {
|
||||
if predicate == nil {
|
||||
panic("predicate func is missing")
|
||||
}
|
||||
@@ -194,22 +225,22 @@ func Some[T any](slice []T, predicate func(index int, t T) bool) bool {
|
||||
}
|
||||
|
||||
// Filter iterates over elements of slice, returning an slice of all elements pass the predicate function
|
||||
func Filter[T any](slice []T, predicate func(index int, t T) bool) []T {
|
||||
func Filter[T any](slice []T, predicate func(index int, item T) bool) []T {
|
||||
if predicate == nil {
|
||||
panic("predicate func is missing")
|
||||
}
|
||||
|
||||
res := make([]T, 0, 0)
|
||||
result := make([]T, 0, 0)
|
||||
for i, v := range slice {
|
||||
if predicate(i, v) {
|
||||
res = append(res, v)
|
||||
result = append(result, v)
|
||||
}
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Count iterates over elements of slice, returns a count of all matched elements
|
||||
func Count[T any](slice []T, predicate func(index int, t T) bool) int {
|
||||
func Count[T any](slice []T, predicate func(index int, item T) bool) int {
|
||||
if predicate == nil {
|
||||
panic("predicate func is missing")
|
||||
}
|
||||
@@ -229,7 +260,7 @@ func Count[T any](slice []T, predicate func(index int, t T) bool) int {
|
||||
}
|
||||
|
||||
// GroupBy iterate over elements of the slice, each element will be group by criteria, returns two slices
|
||||
func GroupBy[T any](slice []T, groupFn func(index int, t T) bool) ([]T, []T) {
|
||||
func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T) {
|
||||
if groupFn == nil {
|
||||
panic("groupFn func is missing")
|
||||
}
|
||||
@@ -253,28 +284,28 @@ func GroupBy[T any](slice []T, groupFn func(index int, t T) bool) ([]T, []T) {
|
||||
return groupA, groupB
|
||||
}
|
||||
|
||||
// GroupWith return a map composed of keys generated from the results of running each element of slice thru iteratee.
|
||||
// GroupWith return a map composed of keys generated from the resultults of running each element of slice thru iteratee.
|
||||
func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T {
|
||||
if iteratee == nil {
|
||||
panic("iteratee func is missing")
|
||||
}
|
||||
|
||||
res := make(map[U][]T)
|
||||
result := make(map[U][]T)
|
||||
|
||||
for _, v := range slice {
|
||||
key := iteratee(v)
|
||||
if _, ok := res[key]; !ok {
|
||||
res[key] = []T{}
|
||||
if _, ok := result[key]; !ok {
|
||||
result[key] = []T{}
|
||||
}
|
||||
res[key] = append(res[key], v)
|
||||
result[key] = append(result[key], v)
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Find iterates over elements of slice, returning the first one that passes a truth test on predicate function.
|
||||
// If return T is nil then no items matched the predicate func
|
||||
func Find[T any](slice []T, predicate func(index int, t T) bool) (*T, bool) {
|
||||
func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) {
|
||||
if predicate == nil {
|
||||
panic("predicate func is missing")
|
||||
}
|
||||
@@ -300,7 +331,7 @@ func Find[T any](slice []T, predicate func(index int, t T) bool) (*T, bool) {
|
||||
|
||||
// FindLast iterates over elements of slice from end to begin, returning the first one that passes a truth test on predicate function.
|
||||
// If return T is nil then no items matched the predicate func
|
||||
func FindLast[T any](slice []T, predicate func(index int, t T) bool) (*T, bool) {
|
||||
func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) {
|
||||
if predicate == nil {
|
||||
panic("predicate func is missing")
|
||||
}
|
||||
@@ -324,13 +355,40 @@ func FindLast[T any](slice []T, predicate func(index int, t T) bool) (*T, bool)
|
||||
return &slice[index], true
|
||||
}
|
||||
|
||||
// Flatten flattens slice with one level
|
||||
func Flatten(slice any) any {
|
||||
sv := sliceValue(slice)
|
||||
|
||||
var result reflect.Value
|
||||
if sv.Type().Elem().Kind() == reflect.Interface {
|
||||
result = reflect.MakeSlice(reflect.TypeOf([]interface{}{}), 0, sv.Len())
|
||||
} else if sv.Type().Elem().Kind() == reflect.Slice {
|
||||
result = reflect.MakeSlice(sv.Type().Elem(), 0, sv.Len())
|
||||
} else {
|
||||
return result
|
||||
}
|
||||
|
||||
for i := 0; i < sv.Len(); i++ {
|
||||
item := reflect.ValueOf(sv.Index(i).Interface())
|
||||
if item.Kind() == reflect.Slice {
|
||||
for j := 0; j < item.Len(); j++ {
|
||||
result = reflect.Append(result, item.Index(j))
|
||||
}
|
||||
} else {
|
||||
result = reflect.Append(result, item)
|
||||
}
|
||||
}
|
||||
|
||||
return result.Interface()
|
||||
}
|
||||
|
||||
// FlattenDeep flattens slice recursive
|
||||
func FlattenDeep(slice any) any {
|
||||
sv := sliceValue(slice)
|
||||
st := sliceElemType(sv.Type())
|
||||
tmp := reflect.MakeSlice(reflect.SliceOf(st), 0, 0)
|
||||
res := flattenRecursive(sv, tmp)
|
||||
return res.Interface()
|
||||
result := flattenRecursive(sv, tmp)
|
||||
return result.Interface()
|
||||
}
|
||||
|
||||
func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value {
|
||||
@@ -349,7 +407,7 @@ func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value {
|
||||
}
|
||||
|
||||
// ForEach iterates over elements of slice and invokes function for each element
|
||||
func ForEach[T any](slice []T, iteratee func(index int, t T)) {
|
||||
func ForEach[T any](slice []T, iteratee func(index int, item T)) {
|
||||
if iteratee == nil {
|
||||
panic("iteratee func is missing")
|
||||
}
|
||||
@@ -360,21 +418,21 @@ func ForEach[T any](slice []T, iteratee func(index int, t T)) {
|
||||
}
|
||||
|
||||
// Map creates an slice of values by running each element of slice thru iteratee function.
|
||||
func Map[T any, U any](slice []T, iteratee func(index int, t T) U) []U {
|
||||
func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U {
|
||||
if iteratee == nil {
|
||||
panic("iteratee func is missing")
|
||||
}
|
||||
|
||||
res := make([]U, len(slice), cap(slice))
|
||||
result := make([]U, len(slice), cap(slice))
|
||||
for i, v := range slice {
|
||||
res[i] = iteratee(i, v)
|
||||
result[i] = iteratee(i, v)
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Reduce creates an slice of values by running each element of slice thru iteratee function.
|
||||
func Reduce[T any](slice []T, iteratee func(index int, t1, t2 T) T, initial T) T {
|
||||
func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initial T) T {
|
||||
if iteratee == nil {
|
||||
panic("iteratee func is missing")
|
||||
}
|
||||
@@ -383,16 +441,16 @@ func Reduce[T any](slice []T, iteratee func(index int, t1, t2 T) T, initial T) T
|
||||
return initial
|
||||
}
|
||||
|
||||
res := iteratee(0, initial, slice[0])
|
||||
result := iteratee(0, initial, slice[0])
|
||||
|
||||
tmp := make([]T, 2, 2)
|
||||
for i := 1; i < len(slice); i++ {
|
||||
tmp[0] = res
|
||||
tmp[0] = result
|
||||
tmp[1] = slice[i]
|
||||
res = iteratee(i, tmp[0], tmp[1])
|
||||
result = iteratee(i, tmp[0], tmp[1])
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// InterfaceSlice convert param to slice of interface.
|
||||
@@ -402,12 +460,12 @@ func InterfaceSlice(slice any) []any {
|
||||
return nil
|
||||
}
|
||||
|
||||
res := make([]any, sv.Len())
|
||||
result := make([]any, sv.Len())
|
||||
for i := 0; i < sv.Len(); i++ {
|
||||
res[i] = sv.Index(i).Interface()
|
||||
result[i] = sv.Index(i).Interface()
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// StringSlice convert param to slice of string.
|
||||
@@ -499,13 +557,11 @@ func InsertAt[T any](slice []T, index int, value any) []T {
|
||||
return slice
|
||||
}
|
||||
|
||||
// value is T
|
||||
if v, ok := value.(T); ok {
|
||||
slice = append(slice[:index], append([]T{v}, slice[index:]...)...)
|
||||
return slice
|
||||
}
|
||||
|
||||
// value is []T
|
||||
if v, ok := value.([]T); ok {
|
||||
slice = append(slice[:index], append(v, slice[index:]...)...)
|
||||
return slice
|
||||
@@ -527,32 +583,47 @@ func UpdateAt[T any](slice []T, index int, value T) []T {
|
||||
}
|
||||
|
||||
// Unique remove duplicate elements in slice.
|
||||
func Unique[T any](slice []T) []T {
|
||||
func Unique[T comparable](slice []T) []T {
|
||||
if len(slice) == 0 {
|
||||
return []T{}
|
||||
}
|
||||
|
||||
// here no use map filter. if use it, the result slice element order is random, not same as origin slice
|
||||
var res []T
|
||||
var result []T
|
||||
for i := 0; i < len(slice); i++ {
|
||||
v := slice[i]
|
||||
skip := true
|
||||
for j := range res {
|
||||
if reflect.DeepEqual(v, res[j]) {
|
||||
for j := range result {
|
||||
if v == result[j] {
|
||||
skip = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if skip {
|
||||
res = append(res, v)
|
||||
result = append(result, v)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// UniqueBy call iteratee func with every item of slice, then remove duplicated.
|
||||
func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T {
|
||||
if len(slice) == 0 {
|
||||
return []T{}
|
||||
}
|
||||
|
||||
var result []T
|
||||
for _, v := range slice {
|
||||
val := iteratee(v)
|
||||
result = append(result, val)
|
||||
}
|
||||
|
||||
return Unique(result)
|
||||
}
|
||||
|
||||
// Union creates a slice of unique values, in order, from all given slices. using == for equality comparisons.
|
||||
func Union[T any](slices ...[]T) []T {
|
||||
func Union[T comparable](slices ...[]T) []T {
|
||||
if len(slices) == 0 {
|
||||
return []T{}
|
||||
}
|
||||
@@ -570,7 +641,7 @@ func Union[T any](slices ...[]T) []T {
|
||||
}
|
||||
|
||||
// Intersection creates a slice of unique values that included by all slices.
|
||||
func Intersection[T any](slices ...[]T) []T {
|
||||
func Intersection[T comparable](slices ...[]T) []T {
|
||||
if len(slices) == 0 {
|
||||
return []T{}
|
||||
}
|
||||
@@ -578,32 +649,38 @@ func Intersection[T any](slices ...[]T) []T {
|
||||
return Unique(slices[0])
|
||||
}
|
||||
|
||||
var res []T
|
||||
var result []T
|
||||
|
||||
reducer := func(s1, s2 []T) []T {
|
||||
s := make([]T, 0, 0)
|
||||
for _, v := range s1 {
|
||||
if Contain(s2, v) {
|
||||
s = append(s, v)
|
||||
reducer := func(sliceA, sliceB []T) []T {
|
||||
hashMap := make(map[T]int)
|
||||
for _, val := range sliceA {
|
||||
hashMap[val] = 1
|
||||
}
|
||||
|
||||
out := make([]T, 0)
|
||||
for _, val := range sliceB {
|
||||
if v, ok := hashMap[val]; v == 1 && ok {
|
||||
out = append(out, val)
|
||||
hashMap[val]++
|
||||
}
|
||||
}
|
||||
return s
|
||||
return out
|
||||
}
|
||||
|
||||
res = reducer(slices[0], slices[1])
|
||||
result = reducer(slices[0], slices[1])
|
||||
|
||||
reduceSlice := make([][]T, 2, 2)
|
||||
for i := 2; i < len(slices); i++ {
|
||||
reduceSlice[0] = res
|
||||
reduceSlice[0] = result
|
||||
reduceSlice[1] = slices[i]
|
||||
res = reducer(reduceSlice[0], reduceSlice[1])
|
||||
result = reducer(reduceSlice[0], reduceSlice[1])
|
||||
}
|
||||
|
||||
return Unique(res)
|
||||
return result
|
||||
}
|
||||
|
||||
// SymmetricDifference oppoiste operation of intersection function
|
||||
func SymmetricDifference[T any](slices ...[]T) []T {
|
||||
func SymmetricDifference[T comparable](slices ...[]T) []T {
|
||||
if len(slices) == 0 {
|
||||
return []T{}
|
||||
}
|
||||
@@ -611,7 +688,7 @@ func SymmetricDifference[T any](slices ...[]T) []T {
|
||||
return Unique(slices[0])
|
||||
}
|
||||
|
||||
res := make([]T, 0)
|
||||
result := make([]T, 0)
|
||||
|
||||
intersectSlice := Intersection(slices...)
|
||||
|
||||
@@ -619,13 +696,13 @@ func SymmetricDifference[T any](slices ...[]T) []T {
|
||||
slice := slices[i]
|
||||
for _, v := range slice {
|
||||
if !Contain(intersectSlice, v) {
|
||||
res = append(res, v)
|
||||
result = append(result, v)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Unique(res)
|
||||
return Unique(result)
|
||||
}
|
||||
|
||||
// Reverse return slice of element order is reversed to the given slice
|
||||
@@ -637,13 +714,12 @@ func Reverse[T any](slice []T) {
|
||||
|
||||
// Shuffle creates an slice of shuffled values
|
||||
func Shuffle[T any](slice []T) []T {
|
||||
|
||||
res := make([]T, len(slice))
|
||||
result := make([]T, len(slice))
|
||||
for i, v := range rand.Perm(len(slice)) {
|
||||
res[i] = slice[v]
|
||||
result[i] = slice[v]
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// SortByField return sorted slice by field
|
||||
@@ -719,7 +795,7 @@ func SortByField(slice any, field string, sortType ...string) error {
|
||||
}
|
||||
|
||||
// Without creates a slice excluding all given values
|
||||
func Without[T any](slice []T, values ...T) []T {
|
||||
func Without[T comparable](slice []T, values ...T) []T {
|
||||
if len(values) == 0 || len(slice) == 0 {
|
||||
return slice
|
||||
}
|
||||
@@ -736,9 +812,9 @@ func Without[T any](slice []T, values ...T) []T {
|
||||
|
||||
// IndexOf returns the index at which the first occurrence of a value is found in a slice or return -1
|
||||
// if the value cannot be found.
|
||||
func IndexOf[T any](slice []T, value T) int {
|
||||
func IndexOf[T comparable](slice []T, value T) int {
|
||||
for i, v := range slice {
|
||||
if reflect.DeepEqual(v, value) {
|
||||
if v == value {
|
||||
return i
|
||||
}
|
||||
}
|
||||
@@ -748,12 +824,30 @@ func IndexOf[T any](slice []T, value T) int {
|
||||
|
||||
// LastIndexOf returns the index at which the last occurrence of a value is found in a slice or return -1
|
||||
// if the value cannot be found.
|
||||
func LastIndexOf[T any](slice []T, value T) int {
|
||||
func LastIndexOf[T comparable](slice []T, value T) int {
|
||||
for i := len(slice) - 1; i > 0; i-- {
|
||||
if reflect.DeepEqual(value, slice[i]) {
|
||||
if value == slice[i] {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
// ToSlicePointer returns a pointer to the slices of a variable parameter transformation
|
||||
func ToSlicePointer[T any](value ...T) []*T {
|
||||
out := make([]*T, len(value))
|
||||
for i := range value {
|
||||
out[i] = &value[i]
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ToSlice returns a slices of a variable parameter transformation
|
||||
func ToSlice[T any](value ...T) []T {
|
||||
out := make([]T, len(value))
|
||||
for i := range value {
|
||||
out[i] = value[i]
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -61,11 +61,39 @@ func TestCompact(t *testing.T) {
|
||||
func TestConcat(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "Concat")
|
||||
|
||||
// assert.Equal([]int{0}, Concat([]int{}, 0))
|
||||
// assert.Equal([]int{1, 2, 3, 4, 5}, Concat([]int{1, 2, 3}, 4, 5))
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, Concat([]int{1, 2, 3}, []int{4, 5}))
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, Concat([]int{1, 2, 3}, []int{4}, []int{5}))
|
||||
// assert.Equal([]int{1, 2, 3, 4, 5}, Concat([]int{1, 2, 3}, []int{4}, 5))
|
||||
}
|
||||
|
||||
func TestEqual(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEqual")
|
||||
|
||||
slice1 := []int{1, 2, 3}
|
||||
slice2 := []int{1, 2, 3}
|
||||
slice3 := []int{3, 2, 1}
|
||||
|
||||
assert.Equal(true, Equal(slice1, slice2))
|
||||
assert.Equal(false, Equal(slice1, slice3))
|
||||
}
|
||||
|
||||
// go test -fuzz=Fuzz -fuzztime=10s .
|
||||
func FuzzEqual(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, a, b []byte) {
|
||||
Equal(a, b)
|
||||
})
|
||||
}
|
||||
|
||||
func TestEqualWith(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEqualWith")
|
||||
|
||||
slice1 := []int{1, 2, 3}
|
||||
slice2 := []int{2, 4, 6}
|
||||
|
||||
isDouble := func(a, b int) bool {
|
||||
return b == a*2
|
||||
}
|
||||
|
||||
assert.Equal(true, EqualWith(slice1, slice2, isDouble))
|
||||
}
|
||||
|
||||
func TestEvery(t *testing.T) {
|
||||
@@ -208,6 +236,14 @@ func TestFindFoundNothing(t *testing.T) {
|
||||
assert.Equal(false, ok)
|
||||
}
|
||||
|
||||
func TestFlatten(t *testing.T) {
|
||||
input := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
|
||||
expected := [][]string{{"a", "b"}, {"c", "d"}}
|
||||
|
||||
assert := internal.NewAssert(t, "TestFlattenDeep")
|
||||
assert.Equal(expected, Flatten(input))
|
||||
}
|
||||
|
||||
func TestFlattenDeep(t *testing.T) {
|
||||
input := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
|
||||
expected := []string{"a", "b", "c", "d"}
|
||||
@@ -371,6 +407,15 @@ func TestUnique(t *testing.T) {
|
||||
assert.Equal([]string{"a", "b", "c"}, Unique([]string{"a", "a", "b", "c"}))
|
||||
}
|
||||
|
||||
func TestUniqueBy(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestUniqueBy")
|
||||
|
||||
actual := UniqueBy([]int{1, 2, 3, 4, 5, 6}, func(val int) int {
|
||||
return val % 4
|
||||
})
|
||||
assert.Equal([]int{1, 2, 3, 0}, actual)
|
||||
}
|
||||
|
||||
func TestUnion(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestUnion")
|
||||
|
||||
@@ -546,3 +591,21 @@ func TestLastIndexOf(t *testing.T) {
|
||||
assert.Equal(1, LastIndexOf(arr, "a"))
|
||||
assert.Equal(-1, LastIndexOf(arr, "d"))
|
||||
}
|
||||
|
||||
func TestToSlice(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToSlice")
|
||||
|
||||
str1 := "a"
|
||||
str2 := "b"
|
||||
assert.Equal([]string{"a"}, ToSlice(str1))
|
||||
assert.Equal([]string{"a", "b"}, ToSlice(str1, str2))
|
||||
}
|
||||
|
||||
func TestToSlicePointer(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToSlicePointer")
|
||||
|
||||
str1 := "a"
|
||||
str2 := "b"
|
||||
assert.Equal([]*string{&str1}, ToSlicePointer(str1))
|
||||
assert.Equal([]*string{&str1, &str2}, ToSlicePointer(str1, str2))
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ func CamelCase(s string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
res := ""
|
||||
result := ""
|
||||
blankSpace := " "
|
||||
regex, _ := regexp.Compile("[-_&]+")
|
||||
ss := regex.ReplaceAllString(s, blankSpace)
|
||||
@@ -26,13 +26,13 @@ func CamelCase(s string) string {
|
||||
if vv[i] >= 65 && vv[i] <= 96 {
|
||||
vv[0] += 32
|
||||
}
|
||||
res += string(vv)
|
||||
result += string(vv)
|
||||
} else {
|
||||
res += Capitalize(v)
|
||||
result += Capitalize(v)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Capitalize converts the first character of a string to upper case and the remaining to lower case.
|
||||
@@ -126,15 +126,15 @@ func KebabCase(s string) string {
|
||||
match := regex.ReplaceAllString(s, blankSpace)
|
||||
rs := strings.Split(match, blankSpace)
|
||||
|
||||
var res []string
|
||||
var result []string
|
||||
for _, v := range rs {
|
||||
splitWords := splitWordsToLower(v)
|
||||
if len(splitWords) > 0 {
|
||||
res = append(res, splitWords...)
|
||||
result = append(result, splitWords...)
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(res, "-")
|
||||
return strings.Join(result, "-")
|
||||
}
|
||||
|
||||
// SnakeCase covert string to snake_case
|
||||
@@ -148,15 +148,15 @@ func SnakeCase(s string) string {
|
||||
match := regex.ReplaceAllString(s, blankSpace)
|
||||
rs := strings.Split(match, blankSpace)
|
||||
|
||||
var res []string
|
||||
var result []string
|
||||
for _, v := range rs {
|
||||
splitWords := splitWordsToLower(v)
|
||||
if len(splitWords) > 0 {
|
||||
res = append(res, splitWords...)
|
||||
result = append(result, splitWords...)
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(res, "_")
|
||||
return strings.Join(result, "_")
|
||||
}
|
||||
|
||||
// Before create substring in source string before position when char first appear
|
||||
|
||||
@@ -4,37 +4,37 @@ import "strings"
|
||||
|
||||
// splitWordsToLower split a string into worlds by uppercase char
|
||||
func splitWordsToLower(s string) []string {
|
||||
var res []string
|
||||
var result []string
|
||||
|
||||
upperIndexes := upperIndex(s)
|
||||
l := len(upperIndexes)
|
||||
if upperIndexes == nil || l == 0 {
|
||||
if s != "" {
|
||||
res = append(res, s)
|
||||
result = append(result, s)
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
if i < l-1 {
|
||||
res = append(res, strings.ToLower(s[upperIndexes[i]:upperIndexes[i+1]]))
|
||||
result = append(result, strings.ToLower(s[upperIndexes[i]:upperIndexes[i+1]]))
|
||||
} else {
|
||||
res = append(res, strings.ToLower(s[upperIndexes[i]:]))
|
||||
result = append(result, strings.ToLower(s[upperIndexes[i]:]))
|
||||
}
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// upperIndex get a int slice which elements are all the uppercase char index of a string
|
||||
func upperIndex(s string) []int {
|
||||
var res []int
|
||||
var result []int
|
||||
for i := 0; i < len(s); i++ {
|
||||
if 64 < s[i] && s[i] < 91 {
|
||||
res = append(res, i)
|
||||
result = append(result, i)
|
||||
}
|
||||
}
|
||||
if len(s) > 0 && res != nil && res[0] != 0 {
|
||||
res = append([]int{0}, res...)
|
||||
if len(s) > 0 && result != nil && result[0] != 0 {
|
||||
result = append([]int{0}, result...)
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -70,3 +70,9 @@ func ExecCommand(command string) (stdout, stderr string, err error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetOsBits get this system bits 32bit or 64bit
|
||||
// return bit int (32/64)
|
||||
func GetOsBits() int {
|
||||
return 32 << (^uint(0) >> 63)
|
||||
}
|
||||
|
||||
@@ -60,3 +60,13 @@ func TestExecCommand(t *testing.T) {
|
||||
assert.IsNotNil(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOsBits(t *testing.T) {
|
||||
osBits := GetOsBits()
|
||||
switch osBits {
|
||||
case 32, 64:
|
||||
t.Logf("os is %d", osBits)
|
||||
default:
|
||||
t.Error("os is not 32 or 64 bits")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user