1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00

Compare commits

...

143 Commits

Author SHA1 Message Date
dudaodong
1ec3a5af87 release v2.0.3 2022-04-06 10:54:54 +08:00
dudaodong
f31dde97b1 docs: add maputil docs in read me file 2022-04-05 14:24:33 +08:00
dudaodong
1718fd1cf1 docs: add doc for maputil package 2022-04-05 14:16:58 +08:00
dudaodong
513c0f829c docs: add doc for SymmetricDifference fun in slice doc 2022-04-05 13:47:13 +08:00
dudaodong
c51a806aff feat: add SymmetricDifference func for set 2022-04-01 18:06:34 +08:00
dudaodong
3c16d50c4b refactor: rename ReverseIntersect to SymmetricDifference 2022-04-01 18:05:02 +08:00
dudaodong
21dd6ab8aa feat: add SymmetricDifference func for set 2022-04-01 18:02:12 +08:00
dudaodong
f5bf5183cc feat: add Minus func for set 2022-04-01 16:48:37 +08:00
dudaodong
f28b5b2f92 feat: add Minus func for set 2022-04-01 16:44:25 +08:00
dudaodong
79867e8a63 feat: add ReverseIntersect function 2022-03-31 19:42:27 +08:00
dudaodong
19939c2b03 feat: add Minus func 2022-03-31 18:00:11 +08:00
dudaodong
bf7ffbfa8d feat: add Intersect func 2022-03-31 16:56:12 +08:00
dudaodong
cbb46f9cb4 feat: add Filter func 2022-03-30 19:52:43 +08:00
dudaodong
3ad142d5d7 feat: add ForEach func 2022-03-30 19:41:55 +08:00
dudaodong
1a436aeb41 feat: add Merge func 2022-03-30 18:06:22 +08:00
dudaodong
1af8fe8daf test: add unit test for Keys and Values func 2022-03-30 17:45:17 +08:00
dudaodong
ae54c8db6f feat: add Values func 2022-03-30 17:34:01 +08:00
dudaodong
be942ec33e feat: add package maputil and Keys func 2022-03-30 17:27:50 +08:00
dudaodong
fafb59dad6 update readme file 2022-03-29 11:02:27 +08:00
dudaodong
e36c01cac9 release v2.0.2 2022-03-29 11:01:31 +08:00
dudaodong
aa0afa8d94 release v1.2.7 2022-03-29 11:01:06 +08:00
dudaodong
18e0031e0e fix: fix TestInsertionSort 2022-03-26 21:06:05 +08:00
dudaodong
a5018c110c fix: fix bug in ToBytes func 2022-03-26 20:54:37 +08:00
dudaodong
142deb83b2 fix: fix InsertionSort bug 2022-03-26 18:25:42 +08:00
dudaodong
ccc0188352 feat: add DeleteValue for SinglyLink 2022-03-24 17:56:45 +08:00
dudaodong
98dba83107 release v2.0.1 2022-03-22 14:47:23 +08:00
dudaodong
9c6aff9030 fix: fix lint warning 'ineffassign' 2022-03-22 14:45:16 +08:00
dudaodong
7fd9a94922 fix: fix lint warning 'ineffassign' 2022-03-22 14:36:35 +08:00
dudaodong
dd3b1f3aed docs: add doc for some new funcs 2022-03-22 14:10:58 +08:00
dudaodong
f9dce592e8 docs: add doc for Min, Max, and Average 2022-03-22 10:43:00 +08:00
dudaodong
c4b0967623 feat: add Max, Min, and Average function 2022-03-22 10:26:43 +08:00
dudaodong
41613061d5 docs: add GroupWith doc 2022-03-21 20:10:39 +08:00
dudaodong
50ef63e27d feat: add GroupWith func 2022-03-21 15:29:10 +08:00
dudaodong
3ae4a35d04 fix: format timezone issue 2022-03-19 19:24:28 +08:00
dudaodong
89ea0ee15a fix: format timezone issue 2022-03-19 19:08:34 +08:00
dudaodong
85399e23ed fix: format timezone issue 2022-03-19 18:42:22 +08:00
dudaodong
19a6f218e6 fix: format time in local timezone 2022-03-19 18:23:06 +08:00
dudaodong
ccaf290b63 docs: add doc for datetime/conversion.go 2022-03-18 18:18:28 +08:00
dudaodong
54745d512c test: add unit test and func comment for time conversion 2022-03-18 17:48:57 +08:00
dudaodong
39234d4722 Merge branch 'main' of github.com:duke-git/lancet into main 2022-03-17 19:46:31 +08:00
dudaodong
4b4310265b fix: update TestListFileNames 2022-03-17 19:46:19 +08:00
wangxudong123
d8a982bf07 增加时间转换 (#25)
Co-authored-by: wangxd01 <wangxd01@mingyuanyun.com>
2022-03-17 19:44:24 +08:00
dudaodong
0334a6f02b docs: fix some issues 2022-03-17 11:55:52 +08:00
dudaodong
ae0c613b8e add package comment 2022-03-17 11:55:08 +08:00
dudaodong
40b2560752 docs: add v2 in import path 2022-03-17 11:33:45 +08:00
dudaodong
50c6e51393 upgrade go module v2 2022-03-17 10:57:35 +08:00
dudaodong
1434e00712 docs: add func HeapSort 2022-03-17 10:11:34 +08:00
dudaodong
76c941cff0 update readme file 2022-03-16 19:39:21 +08:00
dudaodong
bb03f31a8b release v2.0.0 2022-03-16 19:16:43 +08:00
dudaodong
c939b26cb8 refactor: interface{} -> any 2022-03-16 18:41:40 +08:00
dudaodong
af480efa8c docs: add xerror package doc 2022-03-16 18:21:30 +08:00
dudaodong
bc913d70b1 docs: update doc style 2022-03-16 18:06:06 +08:00
dudaodong
2bc87d8a6b docs: add docs/algorithm.md 2022-03-16 18:00:38 +08:00
dudaodong
2185c48eab docs: add docs/algorithm.md 2022-03-16 18:00:29 +08:00
dudaodong
59b5046a15 docs: update slice.md 2022-03-16 16:59:15 +08:00
dudaodong
569902b528 fix: fix lru cache bug 2022-03-14 11:19:30 +08:00
dudaodong
78519088ab feat: add lru cache 2022-03-11 17:05:55 +08:00
dudaodong
0c06cdb29f Merge branch 'main' into v2 2022-03-04 17:42:18 +08:00
dudaodong
e8b8ff8927 merge main branch 2022-03-01 15:00:02 +08:00
dudaodong
06bd407a0c feat: add LevelOrderTraverse func 2022-03-01 11:23:33 +08:00
dudaodong
aa28479d11 feat: update deleteTreeNode func 2022-03-01 11:13:44 +08:00
dudaodong
bf7db0ded2 feat: add DeletetNode 2022-03-01 11:04:38 +08:00
dudaodong
dd1cbf2ee3 refactor: rename Insert to InsertNode 2022-03-01 10:11:37 +08:00
dudaodong
9d5db895c9 Merge branch 'main' into v2 2022-03-01 10:02:23 +08:00
dudaodong
6b09da6e6e feat: add funcs to traverse bstree 2022-02-23 19:34:35 +08:00
dudaodong
b2b6710a1b feat: add BSTree which is binary search tree 2022-02-21 16:48:27 +08:00
dudaodong
e7ee2ed7cf Merge branch 'main' into v2 2022-02-20 11:35:43 +08:00
dudaodong
1dfd1ec1d3 Merge branch 'main' into v2 2022-02-19 21:55:09 +08:00
dudaodong
2e8834a2c1 docs: update slice.doc 2022-02-18 11:05:14 +08:00
dudaodong
df098392c2 merge main branch 2022-02-18 10:28:47 +08:00
dudaodong
5e318a78d2 refactor: remove unused code 2022-02-15 11:19:07 +08:00
dudaodong
d872d64fe0 feat: add CircularQueue 2022-02-15 10:34:14 +08:00
dudaodong
c2257493a8 fix: fix panic info text 2022-02-14 15:36:44 +08:00
dudaodong
48c1f8ffad fix: fix some spell mistake 2022-02-13 19:00:44 +08:00
dudaodong
8a4c8218d2 update func DeQueue comment 2022-02-11 10:49:33 +08:00
dudaodong
92e1321d43 refactor: rename func Length -> Size 2022-02-11 10:48:38 +08:00
dudaodong
43fb907a81 feat: add LinkedQueue 2022-02-11 10:46:48 +08:00
dudaodong
f551c56921 refactor: reconstructure souce file into the corresponding folder 2022-02-10 17:57:53 +08:00
dudaodong
85e1f711f5 feat: and Clear and IsEmpty func 2022-02-10 17:41:51 +08:00
dudaodong
ade567a620 feat: add ArrayQueue data structure 2022-02-10 17:30:37 +08:00
dudaodong
a26e519a3f refactor: rename func Length -> Size 2022-02-10 15:42:05 +08:00
dudaodong
797e47363f rename: rename StackArray -> ArrayStack, StackLink -> LinkedStack 2022-02-10 11:50:03 +08:00
dudaodong
20e1836eb7 rename: rename StackArray -> ArrayStack, StackLink -> LinkedStack 2022-02-10 11:49:46 +08:00
dudaodong
5ae746a1f0 rename: rename InsertByIndex -> InsertAt, UpdateByIndex -> UpdateAt, DeleteByIndex -> DeleteAt for release 2.0 2022-02-10 11:25:34 +08:00
dudaodong
17d271190b feat: add DoublyLink data structure 2022-02-10 10:57:17 +08:00
dudaodong
310f8bd1e1 feat: add Set data structure 2022-02-09 15:15:49 +08:00
dudaodong
bf7a4e729f feat: add func Contain, Union, Intersection 2022-02-09 11:40:08 +08:00
dudaodong
8d0ff28304 update comment for StackLink 2022-02-04 22:45:01 +08:00
dudaodong
cee9bb538f feat: add stacklink.go implements stack with link 2022-02-04 22:42:51 +08:00
dudaodong
eb59d02a08 feat: add stackarray.go implements stack with array 2022-02-04 19:35:06 +08:00
dudaodong
10ed71a3a2 refactor: rename linknode.go to node.go 2022-02-04 09:22:16 +08:00
dudaodong
0e86244559 refactor: rename linknode.go to node.go 2022-02-04 09:21:35 +08:00
dudaodong
5ab150cad3 feat: add DeleteAtHead, DeleteAtTail, DeleteAt, Reverse, Size, GetMiddleNode funcs in singlelink 2022-02-03 16:37:34 +08:00
dudaodong
3546afe86c feat: add some functons of singlelink 2022-02-02 22:41:49 +08:00
dudaodong
70077a6010 merge main branch 2022-01-26 17:47:57 +08:00
dudaodong
efdf36a817 Merge branch 'main' into v2 2022-01-26 17:44:46 +08:00
dudaodong
e233788f69 comment: add comment for List struct 2022-01-26 15:25:52 +08:00
dudaodong
957e6356f6 feat: add singlelink 2022-01-26 15:25:02 +08:00
dudaodong
887eaa528a update: algorithm package comment 2022-01-26 14:57:37 +08:00
dudaodong
33126570bd feat: add datastructure package and list implementation 2022-01-26 14:56:40 +08:00
dudaodong
5937183af0 feat: replace constraints comparable into any in some funcs 2022-01-24 15:47:47 +08:00
dudaodong
4eaa0a39d5 feat: add FindLast func 2022-01-24 15:22:43 +08:00
dudaodong
18ec73839b feat: add DifferenceWith 2022-01-24 14:53:45 +08:00
dudaodong
89aef977a2 refactor: clean code for slice/slice.go 2022-01-24 11:46:09 +08:00
dudaodong
2612569500 merge: merge main branch and refector slice func with generics 2022-01-24 11:10:12 +08:00
dudaodong
acc8b59387 comment: add comment for Unwrap 2022-01-24 10:24:10 +08:00
donutloop
2878d389c8 error: Add unwrap (#24)
Add a unwrap func helper

* Unwrap if err is nil then it returns a valid value otherwise it panics
2022-01-22 21:25:31 +08:00
dudaodong
3f8effb7a3 refactor: make BinarySearch func code clear 2022-01-21 11:57:36 +08:00
dudaodong
bd30855ae6 feat: add LinearSearch 2022-01-21 11:36:31 +08:00
dudaodong
0efe2f57c3 merge main 2022-01-19 20:47:47 +08:00
dudaodong
8868fcabed Merge branch 'main' into v2 2022-01-19 17:35:48 +08:00
dudaodong
dfbb9e30e0 feat: algorithm package, BinarySearch and BinaryIterativeSearch functions 2022-01-17 15:36:48 +08:00
dudaodong
b22be7cade refactor: change var name low -> lowIndex, high -> highIndex 2022-01-17 15:11:33 +08:00
dudaodong
87da6c6816 Merge branch 'main' into v2 2022-01-17 15:01:38 +08:00
dudaodong
912f7052a3 gofmt 2022-01-17 10:29:42 +08:00
dudaodong
e6f9b0954c feat: add CountSort 2022-01-16 17:20:20 +08:00
dudaodong
98e861cf3b feat: add QuickSort, HeapSort, and MergeSort functions 2022-01-16 16:52:17 +08:00
dudaodong
43e0ca7edf feat: add ShellSort 2022-01-14 18:17:46 +08:00
dudaodong
d491bea263 feat: add BubbleSort and InsertionSort 2022-01-14 17:57:14 +08:00
dudaodong
6f1feb96d6 experimental feature, algorithm/sorter.go try to implements sort function with go generics 2022-01-14 17:01:44 +08:00
dudaodong
d46d12f949 feat: add func ContainSubSlice 2022-01-13 11:52:21 +08:00
dudaodong
c6fc92a94c update go version to v1.18 2022-01-12 10:23:04 +08:00
dudaodong
f4fa790b72 Merge branch 'main' into v2 2022-01-12 10:05:35 +08:00
dudaodong
22798fd750 fix: fix some go report issue 2022-01-12 10:01:48 +08:00
dudaodong
907df56f86 update: make func comment consistent 2022-01-11 20:27:06 +08:00
dudaodong
3dadfa234b update: make func comment consistent 2022-01-11 19:33:15 +08:00
donutloop
f1d7154179 refactor: sort (#21)
Removed reverse func because it use to much cpu and add test cas for asc sort
2022-01-11 19:24:36 +08:00
dudaodong
dc47b9ce98 fix: fix confict in readme file 2022-01-11 18:15:09 +08:00
dudaodong
6e626851cf merge #pr20 2022-01-11 18:12:57 +08:00
donutloop
c906d8aea7 Slice: group by and without v2 (#20)
* Slice: group by and without v2

Migrate from reflection to generic

* update doc
2022-01-11 18:11:01 +08:00
dudaodong
e5e4e09308 comment without func 2022-01-11 18:10:21 +08:00
dudaodong
7ed173849a refactor: rewrite DeleteByIndex, InsertByIndex, UpdateByIndex and Without func with generics 2022-01-11 18:08:22 +08:00
donutloop
24c0d95112 Slice: reverse and shufffle v2 (#19)
* Slice: reverse and shufffle v2

Migrate from reflection to generic form

Note: after migration, old reverse must be removed

* Suffle test: remove reflection calls

* Reverse test: change name of test
2022-01-10 19:52:23 +08:00
dudaodong
e9fed34729 fmt: slice.go 2022-01-10 10:27:20 +08:00
dudaodong
9caefdb67d fmt: slice.go 2022-01-10 10:24:33 +08:00
dudaodong
681d5b6bdf update comment for Count func 2022-01-09 22:17:50 +08:00
dudaodong
b0e9758e0d Merge branch 'v2' of github.com:duke-git/lancet into v2 2022-01-09 22:15:18 +08:00
donutloop
7b9a8a55e7 Slice: CountV2 (#18)
Use generic instead of reflection
2022-01-09 22:15:03 +08:00
dudaodong
44ac82e8b8 refactor: rewrite some slice functions with go generics 2022-01-09 22:14:46 +08:00
dudaodong
c4b4cb1173 merge master: rewrite all unit test functions with assert 2022-01-09 18:33:00 +08:00
donutloop
30d798366b Slice: find v2 (#17)
* If slice len is zero then return false
* Convert find to generic form.
* If return T is nil then no items matched the predicate func
2022-01-07 20:19:27 +08:00
dudaodong
3e9a2b5c59 refactor: refact Filter, ForEach, Map func with generics 2022-01-07 17:53:55 +08:00
dudaodong
1343683b08 checkout v2 branch for generics migration 2022-01-07 17:48:00 +08:00
106 changed files with 8356 additions and 1403 deletions

View File

@@ -17,7 +17,7 @@ jobs:
fetch-depth: 2
- uses: actions/setup-go@v2
with:
go-version: "1.16"
go-version: "1.18"
- name: Run coverage
run: go test -v ./... -coverprofile=coverage.txt -covermode=atomic
- name: Upload coverage to Codecov

123
README.md
View File

@@ -4,13 +4,12 @@
<br/>
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-1.2.6-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet)
[![Release](https://img.shields.io/badge/release-2.0.3-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
[![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/duke-git/lancet/blob/main/LICENSE)
</div>
<div STYLE="page-break-after: always;"></div>
@@ -24,14 +23,21 @@ English | [简体中文](./README_zh-CN.md)
## Feature
- 👏 Comprehensive, efficient and reusable.
- 💪 180+ go util functions, support string, slice, datetime, net, crypt...
- 💪 250+ go util functions, support string, slice, datetime, net, crypt...
- 💅 Only depend on the go standard library.
- 🌍 Unit test for every exported function.
## Installation
### Note:
1. <b>For users who use go1.18 and above, it is recommended to install lancet v2.x.x. Cause v2.x.x rewrite all functions with generics of go1.18.</b>
```go
go get github.com/duke-git/lancet
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.7. </b>
```go
go get github.com/duke-git/lancet@v1.2.7 // below go1.18, install latest version of v1.x.x
```
## Usage
@@ -39,7 +45,7 @@ go get github.com/duke-git/lancet
Lancet organizes the code into package structure, and you need to import the corresponding package name when use it. For example, if you use string-related functions,import the strutil package like below:
```go
import "github.com/duke-git/lancet/strutil"
import "github.com/duke-git/lancet/v2/strutil"
```
## Example
@@ -51,7 +57,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -62,10 +68,31 @@ func main() {
```
## API Documentation
### Algorithm package implements some basic algorithm. eg. sort, search.
```go
import "github.com/duke-git/lancet/v2/algorithm"
```
#### Function list:
- [BubbleSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BubbleSort)
- [CountSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#CountSort)
- [HeapSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#HeapSort)
- [InsertionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#InsertionSort)
- [MergeSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#MergeSort)
- [QuickSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#QuickSort)
- [SelectionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#SelectionSort)
- [ShellSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#ShellSort)
- [BinarySearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BinarySearch)
- [BinaryIterativeSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BinaryIterativeSearch)
- [LinearSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LinearSearch)
- [LRUCache](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LRUCache)
### Convertor package contains some functions for data convertion.
```go
import "github.com/duke-git/lancet/convertor"
import "github.com/duke-git/lancet/v2/convertor"
```
#### Function list:
- [ColorHexToRGB](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorHexToRGB)
@@ -81,7 +108,7 @@ import "github.com/duke-git/lancet/convertor"
### Cryptor package is for data encryption and decryption.
```go
import "github.com/duke-git/lancet/cryptor"
import "github.com/duke-git/lancet/v2/cryptor"
```
#### Function list:
@@ -122,7 +149,7 @@ import "github.com/duke-git/lancet/cryptor"
```go
import "github.com/duke-git/lancet/datetime"
import "github.com/duke-git/lancet/v2/datetime"
```
#### Function list:
- [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddDay)
@@ -147,11 +174,19 @@ import "github.com/duke-git/lancet/datetime"
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNightTimestamp)
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatTimeToStr)
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatStrToTime)
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnix)
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnixNow)
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewFormat)
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewISO8601)
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToUnix)
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormat)
- [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)
### Fileutil package implements some basic functions for file operations.
```go
import "github.com/duke-git/lancet/fileutil"
import "github.com/duke-git/lancet/v2/fileutil"
```
#### Function list
@@ -174,7 +209,7 @@ import "github.com/duke-git/lancet/fileutil"
### Formatter contains some functions for data formatting.
```go
import "github.com/duke-git/lancet/formatter"
import "github.com/duke-git/lancet/v2/formatter"
```
#### Function list:
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma)
@@ -182,7 +217,7 @@ import "github.com/duke-git/lancet/formatter"
### Function package can control the flow of function execution and support part of functional programming
```go
import "github.com/duke-git/lancet/function"
import "github.com/duke-git/lancet/v2/function"
```
#### Function list:
@@ -195,16 +230,35 @@ import "github.com/duke-git/lancet/function"
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)
### Mathutil package implements some functions for math calculation.
### Maputil package includes some functions to manipulate map.
```go
import "github.com/duke-git/lancet/mathutil"
import "github.com/duke-git/lancet/v2/maputil"
```
#### Function list:
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ForEach)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Filter)
- [Intersect](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Intersect)
- [Keys](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Keys)
- [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)
### Mathutil package implements some functions for math calculation.
```go
import "github.com/duke-git/lancet/v2/mathutil"
```
#### Function list:
- [Average](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Average)
- [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Exponent)
- [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Fibonacci)
- [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Factorial)
- [Max](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Max)
- [Min](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Min)
- [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Percent)
- [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToFloat)
- [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToString)
@@ -214,7 +268,7 @@ import "github.com/duke-git/lancet/mathutil"
### Netutil package contains functions to get net information and send http request.
```go
import "github.com/duke-git/lancet/netutil"
import "github.com/duke-git/lancet/v2/netutil"
```
#### Function list:
@@ -234,7 +288,7 @@ import "github.com/duke-git/lancet/netutil"
### Random package implements some basic functions to generate random int and string.
```go
import "github.com/duke-git/lancet/random"
import "github.com/duke-git/lancet/v2/random"
```
#### Function list:
@@ -246,7 +300,7 @@ import "github.com/duke-git/lancet/random"
### Retry package is for executing a function repeatedly until it was successful or canceled by the context.
```go
import "github.com/duke-git/lancet/retry"
import "github.com/duke-git/lancet/v2/retry"
```
#### Function list:
@@ -259,7 +313,7 @@ import "github.com/duke-git/lancet/retry"
### Slice contains some functions to manipulate slice.
```go
import "github.com/duke-git/lancet/slice"
import "github.com/duke-git/lancet/v2/slice"
```
#### Function list:
@@ -271,7 +325,8 @@ import "github.com/duke-git/lancet/slice"
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Count)
- [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Difference)
- [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceBy)
- [DeleteByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteByIndex)
- [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)
- [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)
@@ -280,26 +335,27 @@ import "github.com/duke-git/lancet/slice"
- [FlattenDeep](#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)
- [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IntSlice)
- [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InterfaceSlice)
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Intersection)
- [InsertByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InsertByIndex)
- [InsertAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InsertAt)
- [Map](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Map)
- [ReverseSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ReverseSlice)
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reverse)
- [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce)
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Shuffle)
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortByField)
- [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)
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Unique)
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Union)
- [UpdateByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UpdateByIndex)
- [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)
### Strutil package contains some functions to manipulate string.
```go
import "github.com/duke-git/lancet/strutil"
import "github.com/duke-git/lancet/v2/strutil"
```
#### Function list:
@@ -324,9 +380,8 @@ import "github.com/duke-git/lancet/strutil"
### System package contain some functions about os, runtime, shell command.
```go
import "github.com/duke-git/lancet/system"
import "github.com/duke-git/lancet/v2/system"
```
#### Function list:
- [IsWindows](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsWindows)
- [IsLinux](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsLinux)
@@ -340,8 +395,9 @@ import "github.com/duke-git/lancet/system"
### Validator package contains some functions for data validation.
```go
import "github.com/duke-git/lancet/validator"
import "github.com/duke-git/lancet/v2/validator"
```
#### Function list:
- [ContainChinese](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainChinese)
@@ -370,6 +426,13 @@ import "github.com/duke-git/lancet/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)
### xerror package implements helpers for errors.
```go
import "github.com/duke-git/lancet/v2/xerror"
```
#### Function list:
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Unwrap)
## How to Contribute
@@ -380,4 +443,4 @@ I really appreciate any code commits which make lancet lib powerful. Please foll
2. Create your feature branch.
3. Commit your changes.
4. Push to the branch
5. Create new pull request.
5. Create new pull request.

View File

@@ -4,13 +4,12 @@
<br/>
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-1.2.6-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet)
[![Release](https://img.shields.io/badge/release-2.0.3-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
[![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/duke-git/lancet/blob/main/LICENSE)
</div>
<div STYLE="page-break-after: always;"></div>
@@ -24,14 +23,21 @@
## 特性
- 👏 全面、高效、可复用
- 💪 180+常用go工具函数支持string、slice、datetime、net、crypt...
- 💪 250+常用go工具函数支持string、slice、datetime、net、crypt...
- 💅 只依赖go标准库
- 🌍 所有导出函数单元测试覆盖率100%
## 安装
### Note:
1. <b>对于使用go1.18及以上的用户建议安装v2.x.x。 因为v2.x.x用go1.18的泛型重写了大部分函数。</b>
```go
go get github.com/duke-git/lancet
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
```
2. <b>使用go1.18以下版本的用户必须安装v1.x.x。目前最新的v1版本是v1.2.7。</b>
```go
go get github.com/duke-git/lancet@v1.2.7 // 使用go1.18以下版本, 必须安装v1.x.x版本
```
## 用法
@@ -39,7 +45,7 @@ go get github.com/duke-git/lancet
lancet是以包的结构组织代码的使用时需要导入相应的包名。例如如果使用字符串相关函数需要导入strutil包:
```go
import "github.com/duke-git/lancet/strutil"
import "github.com/duke-git/lancet/v2/strutil"
```
## 例子
@@ -51,7 +57,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -62,10 +68,30 @@ func main() {
```
## API文档
### algorithm算法包实现一些基本算法。eg. sort, search.
```go
import "github.com/duke-git/lancet/v2/algorithm"
```
#### Function list:
- [BubbleSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BubbleSort)
- [CountSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#CountSort)
- [HeapSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#HeapSort)
- [InsertionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#InsertionSort)
- [MergeSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#MergeSort)
- [QuickSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#QuickSort)
- [SelectionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#SelectionSort)
- [ShellSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#ShellSort)
- [BinarySearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BinarySearch)
- [BinaryIterativeSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BinaryIterativeSearch)
- [LinearSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LinearSearch)
- [LRUCache](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LRUCache)
### convertor转换器包支持一些常见的数据类型转换。
```go
import "github.com/duke-git/lancet/convertor"
import "github.com/duke-git/lancet/v2/convertor"
```
#### 函数列表:
- [ColorHexToRGB](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ColorHexToRGB)
@@ -81,7 +107,7 @@ import "github.com/duke-git/lancet/convertor"
### cryptor加密包支持数据加密和解密获取md5hash值。支持base64, md5, hmac, aes, des, rsa。
```go
import "github.com/duke-git/lancet/cryptor"
import "github.com/duke-git/lancet/v2/cryptor"
```
#### 函数列表:
@@ -122,7 +148,7 @@ import "github.com/duke-git/lancet/cryptor"
```go
import "github.com/duke-git/lancet/datetime"
import "github.com/duke-git/lancet/v2/datetime"
```
#### 函数列表:
- [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddDay)
@@ -147,11 +173,19 @@ import "github.com/duke-git/lancet/datetime"
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNightTimestamp)
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatTimeToStr)
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatStrToTime)
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnix)
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnixNow)
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewFormat)
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewISO8601)
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToUnix)
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormat)
- [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)
### fileutil包支持文件基本操作。
```go
import "github.com/duke-git/lancet/fileutil"
import "github.com/duke-git/lancet/v2/fileutil"
```
#### 函数列表:
@@ -174,7 +208,7 @@ import "github.com/duke-git/lancet/fileutil"
### formatter格式化器包含一些数据格式化处理方法。
```go
import "github.com/duke-git/lancet/formatter"
import "github.com/duke-git/lancet/v2/formatter"
```
#### 函数列表:
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Comma)
@@ -183,7 +217,7 @@ import "github.com/duke-git/lancet/formatter"
### function函数包控制函数执行流程包含部分函数式编程。
```go
import "github.com/duke-git/lancet/function"
import "github.com/duke-git/lancet/v2/function"
```
#### 函数列表:
@@ -195,16 +229,35 @@ import "github.com/duke-git/lancet/function"
- [Delay](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Delay)
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)
### maputil包包括一些操作map的函数.
```go
import "github.com/duke-git/lancet/v2/maputil"
```
#### 函数列表:
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ForEach)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Filter)
- [Intersect](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Intersect)
- [Keys](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Keys)
- [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)
### mathutil包实现了一些数学计算的函数。
```go
import "github.com/duke-git/lancet/mathutil"
import "github.com/duke-git/lancet/v2/mathutil"
```
#### Function list:
- [Average](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Average)
- [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Exponent)
- [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Fibonacci)
- [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Factorial)
- [Max](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Max)
- [Min](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Min)
- [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Percent)
- [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToFloat)
- [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToString)
@@ -213,7 +266,7 @@ import "github.com/duke-git/lancet/mathutil"
### netutil网络包支持获取ip地址发送http请求。
```go
import "github.com/duke-git/lancet/netutil"
import "github.com/duke-git/lancet/v2/netutil"
```
#### 函数列表:
@@ -233,7 +286,7 @@ import "github.com/duke-git/lancet/netutil"
### random随机数生成器包可以生成随机[]bytes, int, string。
```go
import "github.com/duke-git/lancet/random"
import "github.com/duke-git/lancet/v2/random"
```
#### 函数列表:
@@ -244,7 +297,7 @@ import "github.com/duke-git/lancet/random"
### retry重试执行函数直到函数运行成功或被context cancel。
```go
import "github.com/duke-git/lancet/retry"
import "github.com/duke-git/lancet/v2/retry"
```
#### 函数列表:
@@ -258,7 +311,7 @@ import "github.com/duke-git/lancet/retry"
### slice包包含操作切片的方法集合。
```go
import "github.com/duke-git/lancet/slice"
import "github.com/duke-git/lancet/v2/slice"
```
#### 函数列表:
@@ -270,7 +323,8 @@ import "github.com/duke-git/lancet/slice"
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Count)
- [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Difference)
- [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DifferenceBy)
- [DeleteByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteByIndex)
- [DifferenceWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)
- [DeleteAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteAt)
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Drop)
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Every)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Filter)
@@ -279,27 +333,29 @@ import "github.com/duke-git/lancet/slice"
- [FlattenDeep](#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)
- [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IntSlice)
- [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InterfaceSlice)
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Intersection)
- [InsertByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InsertByIndex)
- [InsertAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InsertAt)
- [Map](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Map)
- [ReverseSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ReverseSlice)
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reverse)
- [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reduce)
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Shuffle)
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortByField)
- [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)
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Unique)
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Union)
- [UpdateByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UpdateByIndex)
- [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)
### strutil包含处理字符串的相关函数。
```go
import "github.com/duke-git/lancet/strutil"
import "github.com/duke-git/lancet/v2/strutil"
```
#### 函数列表:
@@ -325,7 +381,7 @@ import "github.com/duke-git/lancet/strutil"
### system包含os, runtime, shell command相关函数。
```go
import "github.com/duke-git/lancet/system"
import "github.com/duke-git/lancet/v2/system"
```
#### 函数列表:
@@ -341,7 +397,7 @@ import "github.com/duke-git/lancet/system"
### validator验证器包包含常用字符串格式验证函数。
```go
import "github.com/duke-git/lancet/validator"
import "github.com/duke-git/lancet/v2/validator"
```
#### 函数列表:
@@ -372,6 +428,14 @@ import "github.com/duke-git/lancet/validator"
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsUrl)
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsWeakPassword)
validator.md#IsWeakPassword)
### xerror包实现一些错误处理函数
```go
import "github.com/duke-git/lancet/v2/xerror"
```
#### 函数列表:
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Unwrap)
## 如何贡献代码
@@ -381,4 +445,4 @@ import "github.com/duke-git/lancet/validator"
2. 创建自己的特性分支。
3. 提交变更。
4. Push分支。
5. 创建新的pull request。
5. 创建新的pull request。

102
algorithm/lru_cache.go Normal file
View File

@@ -0,0 +1,102 @@
package algorithm
type lruNode[K comparable, V any] struct {
key K
value V
pre *lruNode[K, V]
next *lruNode[K, V]
}
// newLruNode return a lruNode pointer
func newLruNode[K comparable, V any](key K, value V) *lruNode[K, V] {
return &lruNode[K, V]{
key: key,
value: value,
pre: nil,
next: nil,
}
}
// LRUCache lru cache (thread unsafe)
type LRUCache[K comparable, V any] struct {
cache map[K]*lruNode[K, V]
head *lruNode[K, V]
tail *lruNode[K, V]
capacity int
length int
}
// NewLRUCache return a LRUCache pointer
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V] {
return &LRUCache[K, V]{
cache: make(map[K]*lruNode[K, V], capacity),
head: nil,
tail: nil,
capacity: capacity,
length: 0,
}
}
// Get value of key from lru cache
func (l *LRUCache[K, V]) Get(key K) (V, bool) {
var value V
node, ok := l.cache[key]
if ok {
l.moveToHead(node)
return node.value, true
}
return value, false
}
// Put value of key into lru cache
func (l *LRUCache[K, V]) Put(key K, value V) {
node, ok := l.cache[key]
if !ok {
newNode := newLruNode(key, value)
l.cache[key] = newNode
l.addNode(newNode)
if len(l.cache) > l.capacity {
oldKey := l.deleteNode(l.head)
delete(l.cache, oldKey)
}
} else {
node.value = value
l.moveToHead(node)
}
l.length = len(l.cache)
}
func (l *LRUCache[K, V]) addNode(node *lruNode[K, V]) {
if l.tail != nil {
l.tail.next = node
node.pre = l.tail
node.next = nil
}
l.tail = node
if l.head == nil {
l.head = node
}
}
func (l *LRUCache[K, V]) deleteNode(node *lruNode[K, V]) K {
if node == l.tail {
l.tail = l.tail.pre
} else if node == l.head {
l.head = l.head.next
} else {
node.pre.next = node.next
node.next.pre = node.pre
}
return node.key
}
func (l *LRUCache[K, V]) moveToHead(node *lruNode[K, V]) {
if l.tail == node {
return
}
l.deleteNode(node)
l.addNode(node)
}

View File

@@ -0,0 +1,36 @@
package algorithm
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestLRUCache(t *testing.T) {
asssert := internal.NewAssert(t, "TestLRUCache")
cache := NewLRUCache[int, int](2)
cache.Put(1, 1)
cache.Put(2, 2)
_, ok := cache.Get(0)
asssert.Equal(false, ok)
v, ok := cache.Get(1)
asssert.Equal(true, ok)
asssert.Equal(1, v)
v, ok = cache.Get(2)
asssert.Equal(true, ok)
asssert.Equal(2, v)
cache.Put(3, 3)
v, ok = cache.Get(1)
asssert.Equal(false, ok)
asssert.NotEqual(1, v)
v, ok = cache.Get(3)
asssert.Equal(true, ok)
asssert.Equal(3, v)
}

63
algorithm/search.go Normal file
View File

@@ -0,0 +1,63 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package algorithm contain some basic algorithm functions. eg. sort, search, list, linklist, stack, queue, tree, graph. TODO
package algorithm
import "github.com/duke-git/lancet/v2/lancetconstraints"
// Search algorithms see https://github.com/TheAlgorithms/Go/tree/master/search
// LinearSearch Simple linear search algorithm that iterates over all elements of an slice
// If a target is found, the index of the target is returned. Else the function return -1
func LinearSearch[T any](slice []T, target T, comparator lancetconstraints.Comparator) int {
for i, v := range slice {
if comparator.Compare(v, target) == 0 {
return i
}
}
return -1
}
// BinarySearch search for target within a sorted slice, recursive call itself.
// If a target is found, the index of the target is returned. Else the function return -1
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
if highIndex < lowIndex || len(sortedSlice) == 0 {
return -1
}
midIndex := int(lowIndex + (highIndex-lowIndex)/2)
isMidValGreatTarget := comparator.Compare(sortedSlice[midIndex], target) == 1
isMidValLessTarget := comparator.Compare(sortedSlice[midIndex], target) == -1
if isMidValGreatTarget {
return BinarySearch(sortedSlice, target, lowIndex, midIndex-1, comparator)
} else if isMidValLessTarget {
return BinarySearch(sortedSlice, target, midIndex+1, highIndex, comparator)
}
return midIndex
}
// BinaryIterativeSearch search for target within a sorted slice.
// If a target is found, the index of the target is returned. Else the function return -1
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
startIndex := lowIndex
endIndex := highIndex
var midIndex int
for startIndex <= endIndex {
midIndex = int(startIndex + (endIndex-startIndex)/2)
isMidValGreatTarget := comparator.Compare(sortedSlice[midIndex], target) == 1
isMidValLessTarget := comparator.Compare(sortedSlice[midIndex], target) == -1
if isMidValGreatTarget {
endIndex = midIndex - 1
} else if isMidValLessTarget {
startIndex = midIndex + 1
} else {
return midIndex
}
}
return -1
}

33
algorithm/search_test.go Normal file
View File

@@ -0,0 +1,33 @@
package algorithm
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
func TestLinearSearch(t *testing.T) {
asssert := internal.NewAssert(t, "TestLinearSearch")
comparator := &intComparator{}
asssert.Equal(4, LinearSearch(sortedNumbers, 5, comparator))
asssert.Equal(-1, LinearSearch(sortedNumbers, 9, comparator))
}
func TestBinarySearch(t *testing.T) {
asssert := internal.NewAssert(t, "TestBinarySearch")
comparator := &intComparator{}
asssert.Equal(4, BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator))
asssert.Equal(-1, BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator))
}
func TestBinaryIterativeSearch(t *testing.T) {
asssert := internal.NewAssert(t, "TestBinaryIterativeSearch")
comparator := &intComparator{}
asssert.Equal(4, BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator))
asssert.Equal(-1, BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator))
}

208
algorithm/sorter.go Normal file
View File

@@ -0,0 +1,208 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package algorithm contain some basic algorithm functions. eg. sort, search
package algorithm
import "github.com/duke-git/lancet/v2/lancetconstraints"
// BubbleSort use bubble to sort slice.
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
for i := 0; i < len(slice); i++ {
for j := 0; j < len(slice)-1-i; j++ {
isCurrGreatThanNext := comparator.Compare(slice[j], slice[j+1]) == 1
if isCurrGreatThanNext {
swap(slice, j, j+1)
}
}
}
return slice
}
// InsertionSort use insertion to sort slice.
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
size := len(slice)
if size <= 1 {
return slice
}
for i := 1; i < size; i++ {
currentItem := slice[i]
preIndex := i - 1
preItem := slice[preIndex]
isPreLessThanCurrent := comparator.Compare(preItem, currentItem) == -1
for preIndex >= 0 && isPreLessThanCurrent {
slice[preIndex+1] = slice[preIndex]
preIndex--
}
slice[preIndex+1] = currentItem
}
return slice
}
// SelectionSort use selection to sort slice.
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
for i := 0; i < len(slice); i++ {
min := i
for j := i + 1; j < len(slice); j++ {
if comparator.Compare(slice[j], slice[min]) == -1 {
min = j
}
}
swap(slice, i, min)
}
return slice
}
// ShellSort shell sort slice.
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
size := len(slice)
if size <= 1 {
return slice
}
gap := 1
for gap < size/3 {
gap = 3*gap + 1
}
for gap >= 1 {
for i := gap; i < size; i++ {
for j := i; j >= gap && comparator.Compare(slice[j], slice[j-gap]) == -1; j -= gap {
swap(slice, j, j-gap)
}
}
gap /= 3
}
return slice
}
// QuickSort quick sorting for slice, lowIndex is 0 and highIndex is len(slice)-1
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T {
if lowIndex < highIndex {
p := partition(slice, lowIndex, highIndex, comparator)
QuickSort(slice, lowIndex, p-1, comparator)
QuickSort(slice, p+1, highIndex, comparator)
}
return slice
}
// partition split slice into two parts
func partition[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
p := slice[highIndex]
i := lowIndex
for j := lowIndex; j < highIndex; j++ {
if comparator.Compare(slice[j], p) == -1 { //slice[j] < p
swap(slice, i, j)
i++
}
}
swap(slice, i, highIndex)
return i
}
// HeapSort use heap to sort slice
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
size := len(slice)
for i := size/2 - 1; i >= 0; i-- {
sift(slice, i, size-1, comparator)
}
for j := size - 1; j > 0; j-- {
swap(slice, 0, j)
sift(slice, 0, j-1, comparator)
}
return slice
}
func sift[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) {
i := lowIndex
j := 2*i + 1
temp := slice[i]
for j <= highIndex {
if j < highIndex && comparator.Compare(slice[j], slice[j+1]) == -1 { //slice[j] < slice[j+1]
j++
}
if comparator.Compare(temp, slice[j]) == -1 { //tmp < slice[j]
slice[i] = slice[j]
i = j
j = 2*i + 1
} else {
break
}
}
slice[i] = temp
}
// MergeSort merge sorting for slice
func MergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T {
if lowIndex < highIndex {
mid := (lowIndex + highIndex) / 2
MergeSort(slice, lowIndex, mid, comparator)
MergeSort(slice, mid+1, highIndex, comparator)
merge(slice, lowIndex, mid, highIndex, comparator)
}
return slice
}
func merge[T any](slice []T, lowIndex, midIndex, highIndex int, comparator lancetconstraints.Comparator) {
i := lowIndex
j := midIndex + 1
temp := []T{}
for i <= midIndex && j <= highIndex {
//slice[i] < slice[j]
if comparator.Compare(slice[i], slice[j]) == -1 {
temp = append(temp, slice[i])
i++
} else {
temp = append(temp, slice[j])
j++
}
}
if i <= midIndex {
temp = append(temp, slice[i:midIndex+1]...)
} else {
temp = append(temp, slice[j:highIndex+1]...)
}
for k := 0; k < len(temp); k++ {
slice[lowIndex+k] = temp[k]
}
}
// CountSort use count sorting for slice
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
size := len(slice)
out := make([]T, size)
for i := 0; i < size; i++ {
count := 0
for j := 0; j < size; j++ {
//slice[i] > slice[j]
if comparator.Compare(slice[i], slice[j]) == 1 {
count++
}
}
out[count] = slice[i]
}
return out
}
// swap two slice value at index i and j
func swap[T any](slice []T, i, j int) {
slice[i], slice[j] = slice[j], slice[i]
}

177
algorithm/sorter_test.go Normal file
View File

@@ -0,0 +1,177 @@
package algorithm
import (
"fmt"
"testing"
"github.com/duke-git/lancet/v2/internal"
)
// People test mock data
type people struct {
Name string
Age int
}
// PeopleAageComparator sort people slice by age field
type peopleAgeComparator struct{}
// Compare implements github.com/duke-git/lancet/v2/lancetconstraints/constraints.go/Comparator
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
p1, _ := v1.(people)
p2, _ := v2.(people)
//ascending order
if p1.Age < p2.Age {
return -1
} else if p1.Age > p2.Age {
return 1
}
return 0
//decending order
// if p1.Age > p2.Age {
// return -1
// } else if p1.Age < p2.Age {
// return 1
// }
}
var peoples = []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
var intSlice = []int{2, 1, 5, 3, 6, 4}
func TestBubbleSortForStructSlice(t *testing.T) {
asssert := internal.NewAssert(t, "TestBubbleSortForStructSlice")
comparator := &peopleAgeComparator{}
sortedPeopleByAge := BubbleSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge)
asssert.Equal(expected, actual)
}
func TestBubbleSortForIntSlice(t *testing.T) {
asssert := internal.NewAssert(t, "TestBubbleSortForIntSlice")
comparator := &intComparator{}
sortedInt := BubbleSort(intSlice, comparator)
expected := []int{1, 2, 3, 4, 5, 6}
asssert.Equal(expected, sortedInt)
}
func TestInsertionSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestInsertionSort")
comparator := &peopleAgeComparator{}
sortedPeopleByAge := InsertionSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{e 28} {a 20} {c 17} {b 10} {d 8}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge)
asssert.Equal(expected, actual)
}
func TestSelectionSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestSelectionSort")
comparator := &peopleAgeComparator{}
sortedPeopleByAge := SelectionSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge)
asssert.Equal(expected, actual)
}
func TestShellSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestShellSort")
comparator := &peopleAgeComparator{}
sortedPeopleByAge := ShellSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge)
asssert.Equal(expected, actual)
}
func TestQuickSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestQuickSort")
comparator := &peopleAgeComparator{}
sortedPeopleByAge := QuickSort(peoples, 0, len(peoples)-1, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge)
asssert.Equal(expected, actual)
}
func TestHeapSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestHeapSort")
comparator := &peopleAgeComparator{}
sortedPeopleByAge := HeapSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge)
asssert.Equal(expected, actual)
}
func TestMergeSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestMergeSort")
comparator := &peopleAgeComparator{}
sortedPeopleByAge := MergeSort(peoples, 0, len(peoples)-1, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge)
asssert.Equal(expected, actual)
}
func TestCountSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestCountSort")
comparator := &peopleAgeComparator{}
sortedPeopleByAge := CountSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge)
asssert.Equal(expected, actual)
}

View File

@@ -6,9 +6,10 @@ package convertor
import (
"bytes"
"encoding/gob"
"encoding/binary"
"encoding/json"
"fmt"
"math"
"reflect"
"regexp"
"strconv"
@@ -21,14 +22,44 @@ func ToBool(s string) (bool, error) {
}
// ToBytes convert interface to bytes
func ToBytes(data interface{}) ([]byte, error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
err := enc.Encode(data)
if err != nil {
return nil, err
func ToBytes(value any) ([]byte, error) {
v := reflect.ValueOf(value)
switch value.(type) {
case int, int8, int16, int32, int64:
number := v.Int()
buf := bytes.NewBuffer([]byte{})
buf.Reset()
err := binary.Write(buf, binary.BigEndian, number)
return buf.Bytes(), err
case uint, uint8, uint16, uint32, uint64:
number := v.Uint()
buf := bytes.NewBuffer([]byte{})
buf.Reset()
err := binary.Write(buf, binary.BigEndian, number)
return buf.Bytes(), err
case float32:
number := float32(v.Float())
bits := math.Float32bits(number)
bytes := make([]byte, 4)
binary.BigEndian.PutUint32(bytes, bits)
return bytes, nil
case float64:
number := v.Float()
bits := math.Float64bits(number)
bytes := make([]byte, 8)
binary.BigEndian.PutUint64(bytes, bits)
return bytes, nil
case bool:
return strconv.AppendBool([]byte{}, v.Bool()), nil
case string:
return []byte(v.String()), nil
case []byte:
return v.Bytes(), nil
default:
newValue, err := json.Marshal(value)
return newValue, err
}
return buf.Bytes(), nil
}
// ToChar convert string to char slice
@@ -44,7 +75,7 @@ func ToChar(s string) []string {
}
// ToString convert value to string
func ToString(value interface{}) string {
func ToString(value any) string {
res := ""
if value == nil {
return res
@@ -76,7 +107,7 @@ func ToString(value interface{}) string {
}
// ToJson convert value to a valid json string
func ToJson(value interface{}) (string, error) {
func ToJson(value any) (string, error) {
res, err := json.Marshal(value)
if err != nil {
return "", err
@@ -86,7 +117,7 @@ func ToJson(value interface{}) (string, error) {
}
// ToFloat convert value to a float64, if input is not a float return 0.0 and error
func ToFloat(value interface{}) (float64, error) {
func ToFloat(value any) (float64, error) {
v := reflect.ValueOf(value)
res := 0.0
@@ -113,7 +144,7 @@ func ToFloat(value interface{}) (float64, error) {
}
// ToInt convert value to a int64, if input is not a numeric format return 0 and error
func ToInt(value interface{}) (int64, error) {
func ToInt(value any) (int64, error) {
v := reflect.ValueOf(value)
var res int64
@@ -141,7 +172,7 @@ func ToInt(value interface{}) (int64, error) {
// StructToMap convert struct to map, only convert exported struct field
// map key is specified same as struct field tag `json` value
func StructToMap(value interface{}) (map[string]interface{}, error) {
func StructToMap(value any) (map[string]any, error) {
v := reflect.ValueOf(value)
t := reflect.TypeOf(value)
@@ -152,7 +183,7 @@ func StructToMap(value interface{}) (map[string]interface{}, error) {
return nil, fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", value)
}
res := make(map[string]interface{})
res := make(map[string]any)
fieldNum := t.NumField()
pattern := `^[A-Z]`

View File

@@ -4,7 +4,7 @@ import (
"fmt"
"testing"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestToChar(t *testing.T) {
@@ -36,26 +36,33 @@ func TestToBool(t *testing.T) {
func TestToBytes(t *testing.T) {
assert := internal.NewAssert(t, "TestToBytes")
cases := []interface{}{
cases := []any{
0,
false,
"1",
}
expected := [][]byte{
{3, 4, 0, 0},
{3, 2, 0, 0},
{4, 12, 0, 1, 49},
{0, 0, 0, 0, 0, 0, 0, 0},
{102, 97, 108, 115, 101},
{49},
}
for i := 0; i < len(cases); i++ {
actual, _ := ToBytes(cases[i])
assert.Equal(expected[i], actual)
}
bytesData, err := ToBytes("abc")
if err != nil {
t.Error(err)
t.Fail()
}
assert.Equal("abc", ToString(bytesData))
}
func TestToInt(t *testing.T) {
assert := internal.NewAssert(t, "TestToInt")
cases := []interface{}{"123", "-123", 123,
cases := []any{"123", "-123", 123,
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
float32(12.3), float64(12.3),
"abc", false, "111111111111111111111111111111111111111"}
@@ -71,7 +78,7 @@ func TestToInt(t *testing.T) {
func TestToFloat(t *testing.T) {
assert := internal.NewAssert(t, "TestToFloat")
cases := []interface{}{
cases := []any{
"", "-1", "-.11", "1.23e3", ".123e10", "abc",
int(0), int8(1), int16(-1), int32(123), int64(123),
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
@@ -99,7 +106,7 @@ func TestToString(t *testing.T) {
}
aStruct := TestStruct{Name: "TestStruct"}
cases := []interface{}{
cases := []any{
"", nil,
int(0), int8(1), int16(-1), int32(123), int64(123),
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
@@ -147,7 +154,7 @@ func TestStructToMap(t *testing.T) {
100,
}
pm, _ := StructToMap(p)
var expected = map[string]interface{}{"name": "test"}
var expected = map[string]any{"name": "test"}
assert.Equal(expected, pm)
}

View File

@@ -3,7 +3,7 @@ package cryptor
import (
"testing"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestAesEcbEncrypt(t *testing.T) {

View File

@@ -3,7 +3,7 @@ package cryptor
import (
"testing"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestBase64StdEncode(t *testing.T) {

View File

@@ -3,7 +3,7 @@ package cryptor
import (
"testing"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestDesEcbEncrypt(t *testing.T) {

View File

@@ -3,7 +3,7 @@ package cryptor
import (
"testing"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestRsaEncrypt(t *testing.T) {

View File

@@ -0,0 +1,241 @@
package datastructure
import (
"errors"
"fmt"
"github.com/duke-git/lancet/v2/datastructure"
)
// DoublyLink is a linked list. Whose node has a generic Value, Pre pointer points to a previous node of the link, Next pointer points to a next node of the link.
type DoublyLink[T any] struct {
Head *datastructure.LinkNode[T]
length int
}
// NewDoublyLink return *DoublyLink instance
func NewDoublyLink[T any]() *DoublyLink[T] {
return &DoublyLink[T]{Head: nil}
}
// InsertAtHead insert value into doubly linklist at head index
func (link *DoublyLink[T]) InsertAtHead(value T) {
newNode := datastructure.NewLinkNode(value)
size := link.Size()
if size == 0 {
link.Head = newNode
link.length++
return
}
newNode.Next = link.Head
newNode.Pre = nil
link.Head.Pre = newNode
link.Head = newNode
link.length++
}
// InsertAtTail insert value into doubly linklist at tail index
func (link *DoublyLink[T]) InsertAtTail(value T) {
current := link.Head
if current == nil {
link.InsertAtHead(value)
return
}
for current.Next != nil {
current = current.Next
}
newNode := datastructure.NewLinkNode(value)
newNode.Next = nil
newNode.Pre = current
current.Next = newNode
link.length++
}
// InsertAt insert value into doubly linklist at index
func (link *DoublyLink[T]) InsertAt(index int, value T) error {
size := link.length
if index < 0 || index > size {
return errors.New("param index should between 0 and the length of doubly link.")
}
if index == 0 {
link.InsertAtHead(value)
return nil
}
if index == size {
link.InsertAtTail(value)
return nil
}
i := 0
current := link.Head
for current != nil {
if i == index-1 {
newNode := datastructure.NewLinkNode(value)
newNode.Next = current.Next
newNode.Pre = current
current.Next = newNode
link.length++
return nil
}
i++
current = current.Next
}
return errors.New("doubly link list no exist")
}
// DeleteAtHead delete value in doubly linklist at head index
func (link *DoublyLink[T]) DeleteAtHead() error {
if link.Head == nil {
return errors.New("doubly link list no exist")
}
current := link.Head
link.Head = current.Next
link.Head.Pre = nil
link.length--
return nil
}
// DeleteAtTail delete value in doubly linklist at tail index
func (link *DoublyLink[T]) DeleteAtTail() error {
if link.Head == nil {
return errors.New("doubly link list no exist")
}
current := link.Head
if current.Next == nil {
return link.DeleteAtHead()
}
for current.Next.Next != nil {
current = current.Next
}
current.Next = nil
link.length--
return nil
}
// DeleteAt delete value in doubly linklist at index
func (link *DoublyLink[T]) DeleteAt(index int) error {
if link.Head == nil {
return errors.New("doubly link list no exist")
}
current := link.Head
if current.Next == nil || index == 0 {
return link.DeleteAtHead()
}
if index == link.length-1 {
return link.DeleteAtTail()
}
if index < 0 || index > link.length-1 {
return errors.New("param index should between 0 and link size -1.")
}
i := 0
for current != nil {
if i == index-1 {
current.Next = current.Next.Next
link.length--
return nil
}
i++
current = current.Next
}
return errors.New("delete error")
}
// Reverse the linked list
func (link *DoublyLink[T]) Reverse() {
current := link.Head
var temp *datastructure.LinkNode[T]
for current != nil {
temp = current.Pre
current.Pre = current.Next
current.Next = temp
current = current.Pre
}
if temp != nil {
link.Head = temp.Pre
}
}
// GetMiddleNode return node at middle index of linked list
func (link *DoublyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] {
if link.Head == nil {
return nil
}
if link.Head.Next == nil {
return link.Head
}
fast := link.Head
slow := link.Head
for fast != nil {
fast = fast.Next
if fast != nil {
fast = fast.Next
slow = slow.Next
} else {
return slow
}
}
return slow
}
// Size return the count of doubly linked list
func (link *DoublyLink[T]) Size() int {
return link.length
}
// Values return slice of all doubly linklist node value
func (link *DoublyLink[T]) Values() []T {
res := []T{}
current := link.Head
for current != nil {
res = append(res, current.Value)
current = current.Next
}
return res
}
// Print all nodes info of a linked list
func (link *DoublyLink[T]) Print() {
current := link.Head
info := "[ "
for current != nil {
info += fmt.Sprintf("%+v, ", current)
current = current.Next
}
info += " ]"
fmt.Println(info)
}
// IsEmpty checks if link is empty or not
func (link *DoublyLink[T]) IsEmpty() bool {
return link.length == 0
}
// Clear checks if link is empty or not
func (link *DoublyLink[T]) Clear() {
link.Head = nil
link.length = 0
}

View File

@@ -0,0 +1,179 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestDoublyLink_InsertAtFirst(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtFirst")
link := NewDoublyLink[int]()
link.InsertAtHead(1)
link.InsertAtHead(2)
link.InsertAtHead(3)
link.Print()
expected := []int{3, 2, 1}
values := link.Values()
assert.Equal(expected, values)
}
func TestDoublyLink_InsertAtTail(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtTail")
link := NewDoublyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.Print()
expected := []int{1, 2, 3}
values := link.Values()
assert.Equal(expected, values)
}
func TestDoublyLink_InsertAt(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_InsertAt")
link := NewDoublyLink[int]()
err := link.InsertAt(1, 1)
assert.IsNotNil(err)
link.InsertAt(0, 1)
link.InsertAt(1, 2)
link.InsertAt(2, 4)
link.InsertAt(2, 3)
link.Print()
expected := []int{1, 2, 3, 4}
values := link.Values()
assert.Equal(expected, values)
}
func TestDoublyLink_DeleteAtHead(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtHead")
link := NewDoublyLink[int]()
err := link.DeleteAtHead()
assert.IsNotNil(err)
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.DeleteAtHead()
link.Print()
expected := []int{2, 3, 4}
values := link.Values()
assert.Equal(expected, values)
}
func TestDoublyLink_DeleteAtTail(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtTail")
link := NewDoublyLink[int]()
err := link.DeleteAtTail()
assert.IsNotNil(err)
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.DeleteAtTail()
link.Print()
expected := []int{1, 2, 3}
values := link.Values()
assert.Equal(expected, values)
}
func TestDoublyLink_DeleteAt(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAt")
link := NewDoublyLink[int]()
err := link.DeleteAt(0)
assert.IsNotNil(err)
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.InsertAtTail(5)
err = link.DeleteAt(5)
assert.IsNotNil(err)
err = link.DeleteAt(0)
assert.IsNil(err)
assert.Equal([]int{2, 3, 4, 5}, link.Values())
link.DeleteAt(3)
assert.Equal([]int{2, 3, 4}, link.Values())
link.DeleteAt(1)
assert.Equal(2, link.Size())
assert.Equal([]int{2, 4}, link.Values())
}
func TestDoublyLink_Reverse(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_Reverse")
link := NewDoublyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.Reverse()
link.Print()
assert.Equal([]int{4, 3, 2, 1}, link.Values())
}
func TestDoublyLink_GetMiddleNode(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_GetMiddleNode")
link := NewDoublyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
middle1 := link.GetMiddleNode()
assert.Equal(3, middle1.Value)
link.InsertAtTail(5)
link.InsertAtTail(6)
link.InsertAtTail(7)
middle2 := link.GetMiddleNode()
assert.Equal(4, middle2.Value)
}
func TestDoublyLink_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_Clear")
link := NewDoublyLink[int]()
assert.Equal(true, link.IsEmpty())
assert.Equal(0, link.Size())
link.InsertAtTail(1)
assert.Equal(false, link.IsEmpty())
assert.Equal(1, link.Size())
link.Clear()
assert.Equal(true, link.IsEmpty())
assert.Equal(0, link.Size())
}

View File

@@ -0,0 +1,246 @@
package datastructure
import (
"errors"
"fmt"
"reflect"
"github.com/duke-git/lancet/v2/datastructure"
)
// SinglyLink is a linked list. Whose node has a Value generics and Next pointer points to a next node of the link.
type SinglyLink[T any] struct {
Head *datastructure.LinkNode[T]
length int
}
// NewSinglyLink return *SinglyLink instance
func NewSinglyLink[T any]() *SinglyLink[T] {
return &SinglyLink[T]{Head: nil}
}
// InsertAtHead insert value into singly linklist at head index
func (link *SinglyLink[T]) InsertAtHead(value T) {
newNode := datastructure.NewLinkNode(value)
newNode.Next = link.Head
link.Head = newNode
link.length++
}
// InsertAtTail insert value into singly linklist at tail index
func (link *SinglyLink[T]) InsertAtTail(value T) {
current := link.Head
if current == nil {
link.InsertAtHead(value)
return
}
for current.Next != nil {
current = current.Next
}
newNode := datastructure.NewLinkNode(value)
newNode.Next = nil
current.Next = newNode
link.length++
}
// InsertAt insert value into singly linklist at index
func (link *SinglyLink[T]) InsertAt(index int, value T) error {
size := link.length
if index < 0 || index > size {
return errors.New("param index should between 0 and the length of singly link.")
}
if index == 0 {
link.InsertAtHead(value)
return nil
}
if index == size {
link.InsertAtTail(value)
return nil
}
i := 0
current := link.Head
for current != nil {
if i == index-1 {
newNode := datastructure.NewLinkNode(value)
newNode.Next = current.Next
current.Next = newNode
link.length++
return nil
}
i++
current = current.Next
}
return errors.New("singly link list no exist")
}
// DeleteAtHead delete value in singly linklist at head index
func (link *SinglyLink[T]) DeleteAtHead() error {
if link.Head == nil {
return errors.New("singly link list no exist")
}
current := link.Head
link.Head = current.Next
link.length--
return nil
}
// DeleteAtTail delete value in singly linklist at tail index
func (link *SinglyLink[T]) DeleteAtTail() error {
if link.Head == nil {
return errors.New("singly link list no exist")
}
current := link.Head
if current.Next == nil {
return link.DeleteAtHead()
}
for current.Next.Next != nil {
current = current.Next
}
current.Next = nil
link.length--
return nil
}
// DeleteAt delete value in singly linklist at index
func (link *SinglyLink[T]) DeleteAt(index int) error {
if link.Head == nil {
return errors.New("singly link list no exist")
}
current := link.Head
if current.Next == nil || index == 0 {
return link.DeleteAtHead()
}
if index == link.length-1 {
return link.DeleteAtTail()
}
if index < 0 || index > link.length-1 {
return errors.New("param index should between 0 and link size -1.")
}
i := 0
for current != nil {
if i == index-1 {
current.Next = current.Next.Next
link.length--
return nil
}
i++
current = current.Next
}
return errors.New("delete error")
}
// DeleteValue delete value in singly linklist
func (link *SinglyLink[T]) DeleteValue(value T) {
if link.Head == nil {
return
}
dummyHead := datastructure.NewLinkNode(value)
dummyHead.Next = link.Head
current := dummyHead
for current.Next != nil {
if reflect.DeepEqual(current.Next.Value, value) {
current.Next = current.Next.Next
link.length--
} else {
current = current.Next
}
}
link.Head = dummyHead.Next
}
// Reverse the linked list
func (link *SinglyLink[T]) Reverse() {
var pre, next *datastructure.LinkNode[T]
current := link.Head
for current != nil {
next = current.Next
current.Next = pre
pre = current
current = next
}
link.Head = pre
}
// GetMiddleNode return node at middle index of linked list
func (link *SinglyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] {
if link.Head == nil {
return nil
}
if link.Head.Next == nil {
return link.Head
}
fast := link.Head
slow := link.Head
for fast != nil {
fast = fast.Next
if fast != nil {
fast = fast.Next
slow = slow.Next
} else {
return slow
}
}
return slow
}
// Size return the count of singly linked list
func (link *SinglyLink[T]) Size() int {
return link.length
}
// Values return slice of all singly linklist node value
func (link *SinglyLink[T]) Values() []T {
res := []T{}
current := link.Head
for current != nil {
res = append(res, current.Value)
current = current.Next
}
return res
}
// IsEmpty checks if link is empty or not
func (link *SinglyLink[T]) IsEmpty() bool {
return link.length == 0
}
// Clear checks if link is empty or not
func (link *SinglyLink[T]) Clear() {
link.Head = nil
link.length = 0
}
// Print all nodes info of a linked list
func (link *SinglyLink[T]) Print() {
current := link.Head
info := "[ "
for current != nil {
info += fmt.Sprintf("%+v, ", current)
current = current.Next
}
info += " ]"
fmt.Println(info)
}

View File

@@ -0,0 +1,208 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestSinglyLink_InsertAtFirst(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtFirst")
link := NewSinglyLink[int]()
link.InsertAtHead(1)
link.InsertAtHead(2)
link.InsertAtHead(3)
link.Print()
expected := []int{3, 2, 1}
values := link.Values()
assert.Equal(expected, values)
}
func TestSinglyLink_InsertAtTail(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtTail")
link := NewSinglyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.Print()
expected := []int{1, 2, 3}
values := link.Values()
assert.Equal(expected, values)
}
func TestSinglyLink_InsertAt(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_InsertAt")
link := NewSinglyLink[int]()
err := link.InsertAt(1, 1)
assert.IsNotNil(err)
err = link.InsertAt(0, 1)
if err != nil {
t.FailNow()
}
err = link.InsertAt(1, 2)
if err != nil {
t.FailNow()
}
err = link.InsertAt(2, 4)
if err != nil {
t.FailNow()
}
err = link.InsertAt(2, 3)
if err != nil {
t.FailNow()
}
link.Print()
expected := []int{1, 2, 3, 4}
values := link.Values()
assert.Equal(expected, values)
}
func TestSinglyLink_DeleteAtHead(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtHead")
link := NewSinglyLink[int]()
err := link.DeleteAtHead()
assert.IsNotNil(err)
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.DeleteAtHead()
link.Print()
expected := []int{2, 3, 4}
values := link.Values()
assert.Equal(expected, values)
}
func TestSinglyLink_DeleteAtTail(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtTail")
link := NewSinglyLink[int]()
err := link.DeleteAtTail()
assert.IsNotNil(err)
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.DeleteAtTail()
link.Print()
expected := []int{1, 2, 3}
values := link.Values()
assert.Equal(expected, values)
}
func TestSinglyLink_DeleteValue(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_DeleteValue")
link := NewSinglyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.DeleteValue(2)
assert.Equal([]int{1, 3, 4}, link.Values())
link.DeleteValue(1)
assert.Equal([]int{3, 4}, link.Values())
}
func TestSinglyLink_DeleteAt(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAt")
link := NewSinglyLink[int]()
err := link.DeleteAt(0)
assert.IsNotNil(err)
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.InsertAtTail(5)
err = link.DeleteAt(5)
assert.IsNotNil(err)
err = link.DeleteAt(0)
assert.IsNil(err)
assert.Equal([]int{2, 3, 4, 5}, link.Values())
link.DeleteAt(3)
assert.Equal([]int{2, 3, 4}, link.Values())
link.DeleteAt(1)
assert.Equal(2, link.Size())
assert.Equal([]int{2, 4}, link.Values())
}
func TestSinglyLink_Reverse(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_Reverse")
link := NewSinglyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.Reverse()
link.Print()
assert.Equal([]int{4, 3, 2, 1}, link.Values())
}
func TestSinglyLink_GetMiddleNode(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_GetMiddleNode")
link := NewSinglyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
middle1 := link.GetMiddleNode()
assert.Equal(3, middle1.Value)
link.InsertAtTail(5)
link.InsertAtTail(6)
link.InsertAtTail(7)
middle2 := link.GetMiddleNode()
assert.Equal(4, middle2.Value)
}
func TestSinglyLink_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_Clear")
link := NewSinglyLink[int]()
assert.Equal(true, link.IsEmpty())
assert.Equal(0, link.Size())
link.InsertAtTail(1)
assert.Equal(false, link.IsEmpty())
assert.Equal(1, link.Size())
link.Clear()
assert.Equal(true, link.IsEmpty())
assert.Equal(0, link.Size())
}

245
datastructure/list/list.go Normal file
View File

@@ -0,0 +1,245 @@
// 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 (
"reflect"
)
// List is a linear table, implemented with slice
type List[T any] struct {
data []T
}
// NewList return a pointer of List
func NewList[T any](data []T) *List[T] {
return &List[T]{data: data}
}
// Data return list data
func (l *List[T]) Data() []T {
return l.data
}
// ValueOf return the value pointer at index of list data.
func (l *List[T]) ValueOf(index int) (*T, bool) {
if index < 0 || index >= len(l.data) {
return nil, false
}
return &l.data[index], true
}
// IndexOf reture the index of value. if not found return -1
func (l *List[T]) IndexOf(value T) int {
index := -1
data := l.data
for i, v := range data {
if reflect.DeepEqual(v, value) {
index = i
break
}
}
return index
}
// Contain checks if the value in the list or not
func (l *List[T]) Contain(value T) bool {
data := l.data
for _, v := range data {
if reflect.DeepEqual(v, value) {
return true
}
}
return false
}
// Push append value to the list data
func (l *List[T]) Push(value T) {
l.data = append(l.data, value)
}
// InsertAtFirst insert value into list at first index
func (l *List[T]) InsertAtFirst(value T) {
l.InsertAt(0, value)
}
// InsertAtLast insert value into list at last index
func (l *List[T]) InsertAtLast(value T) {
l.InsertAt(len(l.data), value)
}
// InsertAt insert value into list at index
func (l *List[T]) InsertAt(index int, value T) {
data := l.data
size := len(data)
if index < 0 || index > size {
return
}
l.data = append(data[:index], append([]T{value}, data[index:]...)...)
}
// PopFirst delete the first value of list and return it
func (l *List[T]) PopFirst() (*T, bool) {
if len(l.data) == 0 {
return nil, false
}
v := l.data[0]
l.DeleteAt(0)
return &v, true
}
// PopLast delete the last value of list and return it
func (l *List[T]) PopLast() (*T, bool) {
size := len(l.data)
if size == 0 {
return nil, false
}
v := l.data[size-1]
l.DeleteAt(size - 1)
return &v, true
}
// DeleteAt delete the value of list at index
func (l *List[T]) DeleteAt(index int) {
data := l.data
size := len(data)
if index < 0 || index > size-1 {
return
}
if index == size-1 {
data = append(data[:index])
} else {
data = append(data[:index], data[index+1:]...)
}
l.data = data
}
// UpdateAt update value of list at index, index shoud between 0 and list size -1
func (l *List[T]) UpdateAt(index int, value T) {
data := l.data
size := len(data)
if index < 0 || index >= size {
return
}
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 {
if len(l.data) != len(other.data) {
return false
}
for i := 0; i < len(l.data); i++ {
if !reflect.DeepEqual(l.data[i], other.data[i]) {
return false
}
}
return true
}
// IsEmpty check if the list is empty or not
func (l *List[T]) IsEmpty() bool {
return len(l.data) == 0
}
// Clear the data of list
func (l *List[T]) Clear() {
l.data = make([]T, 0, 0)
}
// Clone return a copy of list
func (l *List[T]) Clone() *List[T] {
cl := NewList(make([]T, len(l.data)))
copy(cl.data, l.data)
return cl
}
// Merge two list, return new list, don't change original list
func (l *List[T]) Merge(other *List[T]) *List[T] {
l1, l2 := len(l.data), len(other.data)
ml := NewList(make([]T, l1+l2, l1+l2))
data := append([]T{}, append(l.data, other.data...)...)
ml.data = data
return ml
}
// Size return number of list data items
func (l *List[T]) Size() int {
return len(l.data)
}
// Swap the value of index i and j in list
func (l *List[T]) Swap(i, j int) {
size := len(l.data)
if i < 0 || i >= size || j < 0 || j >= size {
return
}
l.data[i], l.data[j] = l.data[j], l.data[i]
}
// Reverse the item order of list
func (l *List[T]) Reverse() {
for i, j := 0, len(l.data)-1; i < j; i, j = i+1, j-1 {
l.data[i], l.data[j] = l.data[j], l.data[i]
}
}
// Unique remove duplicate items in list
func (l *List[T]) Unique() {
data := l.data
size := len(data)
uniqueData := make([]T, 0, 0)
for i := 0; i < size; i++ {
value := data[i]
skip := true
for _, v := range uniqueData {
if reflect.DeepEqual(value, v) {
skip = false
break
}
}
if skip {
uniqueData = append(uniqueData, value)
}
}
l.data = uniqueData
}
// 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{})
res.data = append(res.data, l.data...)
res.data = append(res.data, other.data...)
res.Unique()
return res
}
// 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))
for _, v := range l.data {
if other.Contain(v) {
res.data = append(res.data, v)
}
}
return res
}

View File

@@ -0,0 +1,272 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestListData(t *testing.T) {
assert := internal.NewAssert(t, "TestListData")
list := NewList([]int{1, 2, 3})
assert.Equal([]int{1, 2, 3}, list.Data())
}
func TestValueOf(t *testing.T) {
assert := internal.NewAssert(t, "TestValueOf")
list := NewList([]int{1, 2, 3})
v, ok := list.ValueOf(0)
assert.Equal(1, *v)
assert.Equal(true, ok)
_, ok = list.ValueOf(3)
assert.Equal(false, ok)
}
func TestIndexOf(t *testing.T) {
assert := internal.NewAssert(t, "TestIndexOf")
list := NewList([]int{1, 2, 3})
i := list.IndexOf(1)
assert.Equal(0, i)
i = list.IndexOf(4)
assert.Equal(-1, i)
}
func TestContain(t *testing.T) {
assert := internal.NewAssert(t, "TestContain")
list := NewList([]int{1, 2, 3})
assert.Equal(true, list.Contain(1))
assert.Equal(false, list.Contain(0))
}
func TestPush(t *testing.T) {
assert := internal.NewAssert(t, "TestPush")
list := NewList([]int{1, 2, 3})
list.Push(4)
assert.Equal([]int{1, 2, 3, 4}, list.Data())
}
func TestInsertAtFirst(t *testing.T) {
assert := internal.NewAssert(t, "TestInsertAtFirst")
list := NewList([]int{1, 2, 3})
list.InsertAtFirst(0)
assert.Equal([]int{0, 1, 2, 3}, list.Data())
}
func TestInsertAtLast(t *testing.T) {
assert := internal.NewAssert(t, "TestInsertAtLast")
list := NewList([]int{1, 2, 3})
list.InsertAtLast(4)
assert.Equal([]int{1, 2, 3, 4}, list.Data())
}
func TestInsertAt(t *testing.T) {
assert := internal.NewAssert(t, "TestInsertAt")
list := NewList([]int{1, 2, 3})
list.InsertAt(-1, 0)
assert.Equal([]int{1, 2, 3}, list.Data())
list.InsertAt(4, 0)
assert.Equal([]int{1, 2, 3}, list.Data())
list.InsertAt(0, 0)
assert.Equal([]int{0, 1, 2, 3}, list.Data())
list.InsertAt(4, 4)
assert.Equal([]int{0, 1, 2, 3, 4}, list.Data())
}
func TestPopFirst(t *testing.T) {
assert := internal.NewAssert(t, "TestPopFirst")
list := NewList([]int{1, 2, 3})
v, ok := list.PopFirst()
assert.Equal(1, *v)
assert.Equal(true, ok)
assert.Equal([]int{2, 3}, list.Data())
list2 := NewList([]int{})
_, ok = list2.PopFirst()
assert.Equal(false, ok)
assert.Equal([]int{}, list2.Data())
}
func TestPopLast(t *testing.T) {
assert := internal.NewAssert(t, "TestPopLast")
list := NewList([]int{1, 2, 3})
v, ok := list.PopLast()
assert.Equal(3, *v)
assert.Equal(true, ok)
assert.Equal([]int{1, 2}, list.Data())
list2 := NewList([]int{})
_, ok = list2.PopLast()
assert.Equal(false, ok)
assert.Equal([]int{}, list2.Data())
}
func TestDeleteAt(t *testing.T) {
assert := internal.NewAssert(t, "TestDeleteAt")
list := NewList([]int{1, 2, 3, 4})
list.DeleteAt(-1)
assert.Equal([]int{1, 2, 3, 4}, list.Data())
list.DeleteAt(4)
assert.Equal([]int{1, 2, 3, 4}, list.Data())
list.DeleteAt(0)
assert.Equal([]int{2, 3, 4}, list.Data())
list.DeleteAt(2)
assert.Equal([]int{2, 3}, list.Data())
}
func TestUpdateAt(t *testing.T) {
assert := internal.NewAssert(t, "TestUpdateAt")
list := NewList([]int{1, 2, 3, 4})
list.UpdateAt(-1, 0)
assert.Equal([]int{1, 2, 3, 4}, list.Data())
list.UpdateAt(4, 0)
assert.Equal([]int{1, 2, 3, 4}, list.Data())
list.UpdateAt(0, 5)
assert.Equal([]int{5, 2, 3, 4}, list.Data())
list.UpdateAt(3, 1)
assert.Equal([]int{5, 2, 3, 1}, list.Data())
}
func TestEqutal(t *testing.T) {
assert := internal.NewAssert(t, "TestEqutal")
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))
}
func TestIsEmpty(t *testing.T) {
assert := internal.NewAssert(t, "TestIsEmpty")
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{})
assert.Equal(false, list1.IsEmpty())
assert.Equal(true, list2.IsEmpty())
}
func TestIsClear(t *testing.T) {
assert := internal.NewAssert(t, "TestIsClear")
list1 := NewList([]int{1, 2, 3, 4})
list1.Clear()
empty := NewList([]int{})
assert.Equal(empty, list1)
}
func TestClone(t *testing.T) {
assert := internal.NewAssert(t, "TestClone")
list1 := NewList([]int{1, 2, 3, 4})
list2 := list1.Clone()
assert.Equal(true, list1.Equtal(list2))
}
func TestMerge(t *testing.T) {
assert := internal.NewAssert(t, "TestMerge")
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{4, 5, 6})
expected := NewList([]int{1, 2, 3, 4, 4, 5, 6})
list3 := list1.Merge(list2)
assert.Equal(true, expected.Equtal(list3))
}
func TestSize(t *testing.T) {
assert := internal.NewAssert(t, "TestSize")
list := NewList([]int{1, 2, 3, 4})
empty := NewList([]int{})
assert.Equal(4, list.Size())
assert.Equal(0, empty.Size())
}
func TestSwap(t *testing.T) {
assert := internal.NewAssert(t, "TestSwap")
list := NewList([]int{1, 2, 3, 4})
expected := NewList([]int{4, 2, 3, 1})
list.Swap(0, 3)
assert.Equal(true, expected.Equtal(list))
}
func TestReverse(t *testing.T) {
assert := internal.NewAssert(t, "TestReverse")
list := NewList([]int{1, 2, 3, 4})
expected := NewList([]int{4, 3, 2, 1})
list.Reverse()
assert.Equal(true, expected.Equtal(list))
}
func TestUnique(t *testing.T) {
assert := internal.NewAssert(t, "TestUnique")
list := NewList([]int{1, 2, 2, 3, 4})
expected := NewList([]int{1, 2, 3, 4})
list.Unique()
assert.Equal(true, expected.Equtal(list))
}
func TestUnion(t *testing.T) {
assert := internal.NewAssert(t, "TestUnion")
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{4, 5, 6})
expected := NewList([]int{1, 2, 3, 4, 5, 6})
list3 := list1.Union(list2)
assert.Equal(true, expected.Equtal(list3))
}
func TestIntersection(t *testing.T) {
assert := internal.NewAssert(t, "TestIntersection")
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{4, 5, 6})
expected := NewList([]int{4})
list3 := list1.Intersection(list2)
assert.Equal(true, expected.Equtal(list3))
}

51
datastructure/node.go Normal file
View File

@@ -0,0 +1,51 @@
// 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
// LinkNode is a linkedlist node, which have a Value and Pre points to previous node, Next points to a next node of the link.
type LinkNode[T any] struct {
Value T
Pre *LinkNode[T]
Next *LinkNode[T]
}
// NewLinkNode return a LinkNode pointer
func NewLinkNode[T any](value T) *LinkNode[T] {
return &LinkNode[T]{value, nil, nil}
}
// StackNode is a node in stack, which have a Value and Next pointer points to next node in the stack.
type StackNode[T any] struct {
Value T
Next *StackNode[T]
}
// NewStackNode return a StackNode pointer
func NewStackNode[T any](value T) *StackNode[T] {
return &StackNode[T]{value, nil}
}
// QueueNode is a node in a queue, which have a Value and Next pointer points to next node in the queue.
type QueueNode[T any] struct {
Value T
Next *QueueNode[T]
}
// NewQueueNode return a QueueNode pointer
func NewQueueNode[T any](value T) *QueueNode[T] {
return &QueueNode[T]{value, nil}
}
// TreeNode is node of tree
type TreeNode[T any] struct {
Data T
Left *TreeNode[T]
Right *TreeNode[T]
}
// NewTreeNode return a TreeNode pointer
func NewTreeNode[T any](data T) *TreeNode[T] {
return &TreeNode[T]{data, nil, nil}
}

View File

@@ -0,0 +1,92 @@
package datastructure
import (
"errors"
"fmt"
"reflect"
)
// ArrayQueue implements queue with slice
type ArrayQueue[T any] struct {
data []T
length int
}
// NewArrayQueue return a empty ArrayQueue pointer
func NewArrayQueue[T any](values ...T) *ArrayQueue[T] {
data := make([]T, len(values))
for i, v := range values {
data[i] = v
}
return &ArrayQueue[T]{data: data, length: len(values)}
}
// Data return queue data
func (q *ArrayQueue[T]) Data() []T {
return q.data
}
// Size return length of queue data
func (q *ArrayQueue[T]) Size() int {
return q.length
}
// IsEmpty checks if queue is empty or not
func (q *ArrayQueue[T]) IsEmpty() bool {
return q.length == 0
}
// Front return front value of queue
func (q *ArrayQueue[T]) Front() T {
return q.data[0]
}
// Back return back value of queue
func (q *ArrayQueue[T]) Back() T {
return q.data[q.length-1]
}
// EnQueue put element into queue
func (q *ArrayQueue[T]) EnQueue(value T) {
q.data = append(q.data, value)
q.length++
}
// DeQueue remove head element of queue and return it, if queue is empty, return nil and error
func (q *ArrayQueue[T]) DeQueue() (*T, error) {
if q.IsEmpty() {
return nil, errors.New("queue is empty")
}
headItem := q.data[0]
q.data = q.data[1:]
q.length--
return &headItem, nil
}
// Clear the queue data
func (q *ArrayQueue[T]) Clear() {
q.data = []T{}
q.length = 0
}
// Contain checks if the value is in queue or not
func (q *ArrayQueue[T]) Contain(value T) bool {
for _, v := range q.data {
if reflect.DeepEqual(v, value) {
return true
}
}
return false
}
// Print queue data
func (q *ArrayQueue[T]) Print() {
info := "["
for _, v := range q.data {
info += fmt.Sprintf("%+v, ", v)
}
info += "]"
fmt.Println(info)
}

View File

@@ -0,0 +1,90 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestArrayQueue_EnQueue(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_EnQueue")
queue := NewArrayQueue[int]()
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
expected := []int{1, 2, 3}
data := queue.Data()
size := queue.Size()
queue.Print()
assert.Equal(expected, data)
assert.Equal(3, size)
}
func TestArrayQueue_DeQueue(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_DeQueue")
queue := NewArrayQueue(1, 2, 3)
val, err := queue.DeQueue()
if err != nil {
t.Fail()
}
queue.Print()
assert.Equal(1, *val)
assert.Equal([]int{2, 3}, queue.Data())
}
func TestArrayQueue_Front(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Front")
queue := NewArrayQueue(1, 2, 3)
val := queue.Front()
queue.Print()
assert.Equal(1, val)
assert.Equal([]int{1, 2, 3}, queue.Data())
}
func TestArrayQueue_Back(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Back")
queue := NewArrayQueue(1, 2, 3)
val := queue.Back()
queue.Print()
assert.Equal(3, val)
assert.Equal([]int{1, 2, 3}, queue.Data())
}
func TestArrayQueue_Contain(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Contain")
queue := NewArrayQueue(1, 2, 3)
assert.Equal(true, queue.Contain(1))
assert.Equal(false, queue.Contain(4))
}
func TestArrayQueue_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Clear")
queue := NewArrayQueue[int]()
assert.Equal(true, queue.IsEmpty())
assert.Equal(0, queue.Size())
queue.EnQueue(1)
assert.Equal(false, queue.IsEmpty())
assert.Equal(1, queue.Size())
queue.Clear()
assert.Equal(true, queue.IsEmpty())
assert.Equal(0, queue.Size())
}

View File

@@ -0,0 +1,118 @@
package datastructure
import (
"errors"
"fmt"
"reflect"
)
// CircularQueue implements circular queue with slice,
// last index of CircularQueue don't contain value, so acturl capacity is size - 1
type CircularQueue[T any] struct {
data []T
front int
rear int
size 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}
}
// Data return queue data
func (q *CircularQueue[T]) Data() []T {
data := []T{}
front := q.front
rear := q.rear
if front <= rear {
return q.data[front:rear]
}
data = append(data, q.data[front:]...)
data = append(data, q.data[0:rear]...)
return data
}
// Length return current data length of queue
func (q *CircularQueue[T]) Length() int {
if q.size == 0 {
return 0
}
return (q.rear - q.front + q.size) % q.size
}
// IsEmpty checks if queue is empty or not
func (q *CircularQueue[T]) IsEmpty() bool {
return q.front == q.rear
}
// IsFull checks if queue is full or not
func (q *CircularQueue[T]) IsFull() bool {
return (q.rear+1)%q.size == q.front
}
// Front return front value of queue
func (q *CircularQueue[T]) Front() T {
return q.data[q.front]
}
// Back return back value of queue
func (q *CircularQueue[T]) Back() T {
if q.rear-1 >= 0 {
return q.data[q.rear-1]
}
return q.data[q.size-1]
}
// 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
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) {
if q.IsEmpty() {
return nil, errors.New("queue is empty")
}
headItem := q.data[q.front]
var t T
q.data[q.front] = t
q.front = (q.front + 1) % q.size
return &headItem, nil
}
// Clear the queue data
func (q *CircularQueue[T]) Clear() {
q.data = []T{}
q.front = 0
q.rear = 0
q.size = 0
}
// Contain checks if the value is in queue or not
func (q *CircularQueue[T]) Contain(value T) bool {
for _, v := range q.data {
if reflect.DeepEqual(v, value) {
return true
}
}
return false
}
// Print queue data
func (q *CircularQueue[T]) Print() {
fmt.Printf("%+v\n", q)
}

View File

@@ -0,0 +1,148 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
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.Print()
// assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
assert.Equal(5, queue.Length())
err := queue.EnQueue(6)
assert.IsNotNil(err)
}
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)
val, err := queue.DeQueue()
assert.IsNil(err)
assert.Equal(1, *val)
assert.Equal(false, queue.IsFull())
val, _ = queue.DeQueue()
queue.Print()
assert.Equal(2, *val)
queue.EnQueue(6)
queue.Print()
assert.Equal(false, queue.IsFull())
}
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.Print()
queue.DeQueue()
queue.DeQueue()
queue.EnQueue(6)
queue.EnQueue(7)
queue.Print()
val := queue.Front()
assert.Equal(3, val)
assert.Equal(5, queue.Length())
}
func TestCircularQueue_Back(t *testing.T) {
assert := internal.NewAssert(t, "TestCircularQueue_Back")
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.Print()
assert.Equal(5, queue.Back())
queue.DeQueue()
queue.DeQueue()
queue.EnQueue(6)
queue.EnQueue(7)
queue.Print()
assert.Equal(7, queue.Back())
}
func TestCircularQueue_Contain(t *testing.T) {
assert := internal.NewAssert(t, "TestCircularQueue_Contain")
queue := NewCircularQueue[int](2)
queue.EnQueue(1)
assert.Equal(true, queue.Contain(1))
assert.Equal(false, queue.Contain(2))
}
func TestCircularQueue_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestCircularQueue_Clear")
queue := NewCircularQueue[int](3)
assert.Equal(true, queue.IsEmpty())
assert.Equal(0, queue.Length())
queue.EnQueue(1)
assert.Equal(false, queue.IsEmpty())
assert.Equal(1, queue.Length())
queue.Clear()
assert.Equal(true, queue.IsEmpty())
assert.Equal(0, queue.Length())
}
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.Print()
assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
queue.DeQueue()
queue.DeQueue()
queue.EnQueue(6)
queue.EnQueue(7)
queue.Print()
assert.Equal([]int{3, 4, 5, 6, 7}, queue.Data())
}

View File

@@ -0,0 +1,104 @@
package datastructure
import (
"errors"
"fmt"
"github.com/duke-git/lancet/v2/datastructure"
)
// LinkedQueue implements queue with link list
type LinkedQueue[T any] struct {
head *datastructure.QueueNode[T]
tail *datastructure.QueueNode[T]
length int
}
// NewLinkedQueue return a empty LinkedQueue pointer
func NewLinkedQueue[T any]() *LinkedQueue[T] {
return &LinkedQueue[T]{head: nil, tail: nil, length: 0}
}
// Data return queue data
func (q *LinkedQueue[T]) Data() []T {
res := []T{}
current := q.head
for current != nil {
res = append(res, current.Value)
current = current.Next
}
return res
}
// Size return length of queue data
func (q *LinkedQueue[T]) Size() int {
return q.length
}
// IsEmpty checks if queue is empty or not
func (q *LinkedQueue[T]) IsEmpty() bool {
return q.length == 0
}
// EnQueue add element into queue
func (q *LinkedQueue[T]) EnQueue(value T) {
newNode := datastructure.NewQueueNode(value)
if q.IsEmpty() {
q.head = newNode
q.tail = newNode
} else {
q.tail.Next = newNode
q.tail = newNode
}
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) {
if q.IsEmpty() {
return nil, errors.New("queue is empty")
}
head := q.head
q.head = q.head.Next
q.length--
return &head.Value, nil
}
// Front return front value of queue
func (q *LinkedQueue[T]) Front() (*T, error) {
if q.IsEmpty() {
return nil, errors.New("queue is empty")
}
return &q.head.Value, nil
}
// Back return back value of queue
func (q *LinkedQueue[T]) Back() (*T, error) {
if q.IsEmpty() {
return nil, errors.New("queue is empty")
}
return &q.tail.Value, nil
}
// Clear clear the queue data
func (q *LinkedQueue[T]) Clear() {
q.head = nil
q.tail = nil
q.length = 0
}
// Print all nodes info of queue link
func (q *LinkedQueue[T]) Print() {
current := q.head
info := "[ "
for current != nil {
info += fmt.Sprintf("%+v, ", current)
current = current.Next
}
info += " ]"
fmt.Println(info)
}

View File

@@ -0,0 +1,84 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
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.Print()
assert.Equal([]int{1, 2, 3}, queue.Data())
assert.Equal(3, queue.Size())
}
func TestLinkedQueue_DeQueue(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedQueue_DeQueue")
queue := NewLinkedQueue[int]()
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
val, _ := queue.DeQueue()
queue.Print()
assert.Equal([]int{2, 3}, queue.Data())
assert.Equal(1, *val)
}
func TestLinkedQueue_Front(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedQueue_Front")
queue := NewLinkedQueue[int]()
_, err := queue.Front()
assert.IsNotNil(err)
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
val, err := queue.Front()
assert.Equal(1, *val)
assert.IsNil(err)
}
func TestLinkedQueue_Back(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
queue := NewLinkedQueue[int]()
_, err := queue.Back()
assert.IsNotNil(err)
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
val, err := queue.Back()
assert.Equal(3, *val)
assert.IsNil(err)
}
func TestLinkedQueue_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
queue := NewLinkedQueue[int]()
assert.Equal(true, queue.IsEmpty())
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
assert.Equal(false, queue.IsEmpty())
queue.Clear()
assert.Equal(true, queue.IsEmpty())
}

136
datastructure/set/set.go Normal file
View File

@@ -0,0 +1,136 @@
package datastructure
// Set is a data container, like slice, but element of set is not duplicate
type Set[T comparable] map[T]bool
// NewSet return a instance of set
func NewSet[T comparable](values ...T) Set[T] {
set := make(Set[T])
set.Add(values...)
return set
}
// Add value to set
func (s Set[T]) Add(values ...T) {
for _, v := range values {
s[v] = true
}
}
// Contain checks if set contains value or not
func (s Set[T]) Contain(value T) bool {
_, ok := s[value]
return ok
}
// Contain checks if set contains other set
func (s Set[T]) ContainAll(other Set[T]) bool {
for k := range other {
_, ok := s[k]
if !ok {
return false
}
}
return true
}
// Clone return a copy of set
func (s Set[T]) Clone() Set[T] {
set := NewSet[T]()
set.Add(s.Values()...)
return set
}
// Delete value of set
func (s Set[T]) Delete(values ...T) {
for _, v := range values {
delete(s, v)
}
}
// Equal checks if two set has same elements or not
func (s Set[T]) Equal(other Set[T]) bool {
if s.Size() != other.Size() {
return false
}
return s.ContainAll(other) && other.ContainAll(s)
}
// Iterate call function by every element of set
func (s Set[T]) Iterate(fn func(value T)) {
for v := range s {
fn(v)
}
}
// IsEmpty checks the set is empty or not
func (s Set[T]) IsEmpty() bool {
return len(s) == 0
}
// Size get the number of elements in set
func (s Set[T]) Size() int {
return len(s)
}
// Values return all values of set
func (s Set[T]) Values() []T {
values := make([]T, 0, 0)
s.Iterate(func(value T) {
values = append(values, value)
})
return values
}
// Union creates a new set contain all element of set s and other
func (s Set[T]) Union(other Set[T]) Set[T] {
set := s.Clone()
set.Add(other.Values()...)
return set
}
// Intersection creates a new set whose element both be contained in set s and other
func (s Set[T]) Intersection(other Set[T]) Set[T] {
set := NewSet[T]()
s.Iterate(func(value T) {
if other.Contain(value) {
set.Add(value)
}
})
return set
}
// SymmetricDifference creates a new set whose element is in set1 or set2, but not in both sets
func (s Set[T]) SymmetricDifference(other Set[T]) Set[T] {
set := NewSet[T]()
s.Iterate(func(value T) {
if !other.Contain(value) {
set.Add(value)
}
})
other.Iterate(func(value T) {
if !s.Contain(value) {
set.Add(value)
}
})
return set
}
// Minus creates an set of whose element in origin set but not in compared set
func (s Set[T]) Minus(comparedSet Set[T]) Set[T] {
set := NewSet[T]()
s.Iterate(func(value T) {
if !comparedSet.Contain(value) {
set.Add(value)
}
})
return set
}

View File

@@ -0,0 +1,149 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestSet_Add(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Add")
set := NewSet[int]()
set.Add(1, 2, 3)
expected := NewSet(1, 2, 3)
assert.Equal(true, set.Equal(expected))
}
func TestSet_Contain(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Contain")
set := NewSet[int]()
set.Add(1, 2, 3)
assert.Equal(true, set.Contain(1))
assert.Equal(false, set.Contain(4))
}
func TestSet_ContainAll(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_ContainAll")
set1 := NewSet(1, 2, 3)
set2 := NewSet(1, 2)
set3 := NewSet(1, 2, 3, 4)
assert.Equal(true, set1.ContainAll(set2))
assert.Equal(false, set1.ContainAll(set3))
}
func TestSet_Clone(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Clone")
set1 := NewSet(1, 2, 3)
set2 := set1.Clone()
assert.Equal(true, set1.Size() == set2.Size())
assert.Equal(true, set1.ContainAll(set2))
}
func TestSet_Delete(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Delete")
set := NewSet[int]()
set.Add(1, 2, 3)
set.Delete(3)
expected := NewSet(1, 2)
assert.Equal(true, set.Equal(expected))
}
func TestSet_Equal(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Equal")
set1 := NewSet(1, 2, 3)
set2 := NewSet(1, 2, 3)
set3 := NewSet(1, 2, 3, 4)
assert.Equal(true, set1.Equal(set2))
assert.Equal(false, set1.Equal(set3))
}
func TestSet_Iterate(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Iterate")
set := NewSet(1, 2, 3)
arr := []int{}
set.Iterate(func(value int) {
arr = append(arr, value)
})
assert.Equal(3, len(arr))
}
func TestSet_IsEmpty(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_IsEmpty")
set := NewSet[int]()
assert.Equal(true, set.IsEmpty())
}
func TestSet_Size(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Size")
set := NewSet(1, 2, 3)
assert.Equal(3, set.Size())
}
func TestSet_Values(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Values")
set := NewSet(1, 2, 3)
values := set.Values()
assert.Equal(3, len(values))
}
func TestSet_Union(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Union")
set1 := NewSet(1, 2, 3)
set2 := NewSet(2, 3, 4, 5)
expected := NewSet(1, 2, 3, 4, 5)
unionSet := set1.Union(set2)
assert.Equal(expected, unionSet)
}
func TestSet_Intersection(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Intersection")
set1 := NewSet(1, 2, 3)
set2 := NewSet(2, 3, 4, 5)
expected := NewSet(2, 3)
intersectionSet := set1.Intersection(set2)
assert.Equal(expected, intersectionSet)
}
func TestSet_SymmetricDifference(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_SymmetricDifference")
set1 := NewSet(1, 2, 3)
set2 := NewSet(2, 3, 4, 5)
assert.Equal(NewSet(1, 4, 5), set1.SymmetricDifference(set2))
}
func TestSet_Minus(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Minus")
set1 := NewSet(1, 2, 3)
set2 := NewSet(2, 3, 4, 5)
set3 := NewSet(2, 3)
assert.Equal(NewSet(1), set1.Minus(set2))
assert.Equal(NewSet(4, 5), set2.Minus(set3))
}

View File

@@ -0,0 +1,62 @@
package datastructure
import "errors"
// ArrayStack implements stack with slice
type ArrayStack[T any] struct {
data []T
length int
}
// NewArrayStack return a empty ArrayStack pointer
func NewArrayStack[T any]() *ArrayStack[T] {
return &ArrayStack[T]{data: []T{}, length: 0}
}
// Data return stack data
func (s *ArrayStack[T]) Data() []T {
return s.data
}
// Size return length of stack data
func (s *ArrayStack[T]) Size() int {
return s.length
}
// IsEmpty checks if stack is empty or not
func (s *ArrayStack[T]) IsEmpty() bool {
return s.length == 0
}
// Push element into stack
func (s *ArrayStack[T]) Push(value T) {
s.data = append([]T{value}, s.data...)
s.length++
}
// Pop delete the top element of stack then return it, if stack is empty, return nil and error
func (s *ArrayStack[T]) Pop() (*T, error) {
if s.IsEmpty() {
return nil, errors.New("stack is empty")
}
topItem := s.data[0]
s.data = s.data[1:]
s.length--
return &topItem, nil
}
// Peak return the top element of stack then return it
func (s *ArrayStack[T]) Peak() (*T, error) {
if s.IsEmpty() {
return nil, errors.New("stack is empty")
}
return &s.data[0], nil
}
// Clear the stack data
func (s *ArrayStack[T]) Clear() {
s.data = []T{}
s.length = 0
}

View File

@@ -0,0 +1,77 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestArrayStack_Push(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayStack_Push")
stack := NewArrayStack[int]()
stack.Push(1)
stack.Push(2)
stack.Push(3)
expected := []int{3, 2, 1}
values := stack.Data()
length := stack.Size()
assert.Equal(expected, values)
assert.Equal(3, length)
}
func TestArrayStack_Pop(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayStack_Pop")
stack := NewArrayStack[int]()
_, err := stack.Pop()
assert.IsNotNil(err)
stack.Push(1)
stack.Push(2)
stack.Push(3)
topItem, err := stack.Pop()
assert.IsNil(err)
assert.Equal(3, *topItem)
expected := []int{2, 1}
assert.Equal(expected, stack.Data())
}
func TestArrayStack_Peak(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayStack_Peak")
stack := NewArrayStack[int]()
_, err := stack.Peak()
assert.IsNotNil(err)
stack.Push(1)
stack.Push(2)
stack.Push(3)
topItem, err := stack.Peak()
assert.IsNil(err)
assert.Equal(3, *topItem)
expected := []int{3, 2, 1}
assert.Equal(expected, stack.Data())
}
func TestArrayStack_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayStack_Clear")
stack := NewArrayStack[int]()
assert.Equal(true, stack.IsEmpty())
assert.Equal(0, stack.Size())
stack.Push(1)
assert.Equal(false, stack.IsEmpty())
assert.Equal(1, stack.Size())
stack.Clear()
assert.Equal(true, stack.IsEmpty())
assert.Equal(0, stack.Size())
}

View File

@@ -0,0 +1,94 @@
package datastructure
import (
"errors"
"fmt"
"github.com/duke-git/lancet/v2/datastructure"
)
// LinkedStack implements stack with link list
type LinkedStack[T any] struct {
top *datastructure.StackNode[T]
length int
}
// NewLinkedStack return a empty LinkedStack pointer
func NewLinkedStack[T any]() *LinkedStack[T] {
return &LinkedStack[T]{top: nil, length: 0}
}
// Data return stack data
func (s *LinkedStack[T]) Data() []T {
res := []T{}
current := s.top
for current != nil {
res = append(res, current.Value)
current = current.Next
}
return res
}
// Size return length of stack data
func (s *LinkedStack[T]) Size() int {
return s.length
}
// IsEmpty checks if stack is empty or not
func (s *LinkedStack[T]) IsEmpty() bool {
return s.length == 0
}
// Push element into stack
func (s *LinkedStack[T]) Push(value T) {
newNode := datastructure.NewStackNode(value)
top := s.top
if top == nil {
s.top = newNode
} else {
newNode.Next = top
s.top = newNode
}
s.length++
}
// Pop delete the top element of stack then return it, if stack is empty, return nil and error
func (s *LinkedStack[T]) Pop() (*T, error) {
if s.IsEmpty() {
return nil, errors.New("stack is empty")
}
top := s.top
s.top = s.top.Next
s.length--
return &top.Value, nil
}
// Peak return the top element of stack then return it
func (s *LinkedStack[T]) Peak() (*T, error) {
if s.IsEmpty() {
return nil, errors.New("stack is empty")
}
return &s.top.Value, nil
}
// Clear clear the stack data
func (s *LinkedStack[T]) Clear() {
s.top = nil
s.length = 0
}
// Print all nodes info of stack link
func (s *LinkedStack[T]) Print() {
current := s.top
info := "[ "
for current != nil {
info += fmt.Sprintf("%+v, ", current)
current = current.Next
}
info += " ]"
fmt.Println(info)
}

View File

@@ -0,0 +1,80 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestLinkedStack_Push(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedStack_Push")
stack := NewLinkedStack[int]()
stack.Push(1)
stack.Push(2)
stack.Push(3)
stack.Print()
expected := []int{3, 2, 1}
values := stack.Data()
size := stack.Size()
assert.Equal(expected, values)
assert.Equal(3, size)
}
func TestLinkedStack_Pop(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedStack_Pop")
stack := NewLinkedStack[int]()
_, err := stack.Pop()
assert.IsNotNil(err)
stack.Push(1)
stack.Push(2)
stack.Push(3)
topItem, err := stack.Pop()
assert.IsNil(err)
assert.Equal(3, *topItem)
expected := []int{2, 1}
stack.Print()
assert.Equal(expected, stack.Data())
}
func TestLinkedStack_Peak(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedStack_Peak")
stack := NewLinkedStack[int]()
_, err := stack.Peak()
assert.IsNotNil(err)
stack.Push(1)
stack.Push(2)
stack.Push(3)
topItem, err := stack.Peak()
assert.IsNil(err)
assert.Equal(3, *topItem)
expected := []int{3, 2, 1}
assert.Equal(expected, stack.Data())
}
func TestLinkedStack_Empty(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedStack_Empty")
stack := NewLinkedStack[int]()
assert.Equal(true, stack.IsEmpty())
assert.Equal(0, stack.Size())
stack.Push(1)
assert.Equal(false, stack.IsEmpty())
assert.Equal(1, stack.Size())
stack.Clear()
assert.Equal(true, stack.IsEmpty())
assert.Equal(0, stack.Size())
}

View File

@@ -0,0 +1,83 @@
package datastructure
import (
"math"
"github.com/duke-git/lancet/v2/datastructure"
"github.com/duke-git/lancet/v2/lancetconstraints"
)
// BSTree is a binary search tree data structure in which each node has at most 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.
type BSTree[T any] struct {
root *datastructure.TreeNode[T]
}
// NewBSTree create a BSTree pointer
func NewBSTree[T any](rootData T) *BSTree[T] {
root := datastructure.NewTreeNode(rootData)
return &BSTree[T]{root}
}
// InsertNode insert data into BSTree
func (t *BSTree[T]) InsertNode(data T, comparator lancetconstraints.Comparator) {
root := t.root
newNode := datastructure.NewTreeNode(data)
if root == nil {
t.root = newNode
} else {
insertTreeNode(root, newNode, comparator)
}
}
// DeletetNode delete data into BSTree
func (t *BSTree[T]) DeletetNode(data T, comparator lancetconstraints.Comparator) {
deleteTreeNode(t.root, data, comparator)
}
// NodeLevel get node level in BSTree
func (t *BSTree[T]) NodeLevel(node *datastructure.TreeNode[T]) int {
if node == nil {
return 0
}
left := float64(t.NodeLevel(node.Left))
right := float64(t.NodeLevel(node.Right))
return int(math.Max(left, right)) + 1
}
// PreOrderTraverse traverse tree node in pre order
func (t *BSTree[T]) PreOrderTraverse() []T {
return preOrderTraverse(t.root)
}
// PostOrderTraverse traverse tree node in post order
func (t *BSTree[T]) PostOrderTraverse() []T {
return postOrderTraverse(t.root)
}
// InOrderTraverse traverse tree node in mid order
func (t *BSTree[T]) InOrderTraverse() []T {
return inOrderTraverse(t.root)
}
// LevelOrderTraverse traverse tree node in level order
func (t *BSTree[T]) LevelOrderTraverse() []T {
traversal := make([]T, 0)
levelOrderTraverse(t.root, &traversal)
return traversal
}
// Depth returns the calculated depth of a binary saerch tree
func (t *BSTree[T]) Depth() int {
return calculateDepth(t.root, 0)
}
// Print the bstree structure
func (t *BSTree[T]) Print() {
maxLevel := t.NodeLevel(t.root)
nodes := []*datastructure.TreeNode[T]{t.root}
printTreeNodes(nodes, 1, maxLevel)
}

View File

@@ -0,0 +1,142 @@
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 TestBSTree_InsertNode(t *testing.T) {
bstree := NewBSTree(6)
comparator := &intComparator{}
bstree.InsertNode(7, comparator)
bstree.InsertNode(5, comparator)
bstree.InsertNode(2, comparator)
bstree.InsertNode(4, comparator)
bstree.Print()
}
func TestBSTree_PreOrderTraverse(t *testing.T) {
assert := internal.NewAssert(t, "TestBSTree_PreOrderTraverse")
bstree := NewBSTree(6)
comparator := &intComparator{}
bstree.InsertNode(7, comparator)
bstree.InsertNode(5, comparator)
bstree.InsertNode(2, comparator)
bstree.InsertNode(4, comparator)
acturl := bstree.PreOrderTraverse()
t.Log(acturl)
assert.Equal([]int{6, 5, 2, 4, 7}, acturl)
}
func TestBSTree_PostOrderTraverse(t *testing.T) {
assert := internal.NewAssert(t, "TestBSTree_PostOrderTraverse")
bstree := NewBSTree(6)
comparator := &intComparator{}
bstree.InsertNode(7, comparator)
bstree.InsertNode(5, comparator)
bstree.InsertNode(2, comparator)
bstree.InsertNode(4, comparator)
acturl := bstree.PostOrderTraverse()
t.Log(acturl)
assert.Equal([]int{5, 2, 4, 7, 6}, acturl)
}
func TestBSTree_InOrderTraverse(t *testing.T) {
assert := internal.NewAssert(t, "TestBSTree_InOrderTraverse")
bstree := NewBSTree(6)
comparator := &intComparator{}
bstree.InsertNode(7, comparator)
bstree.InsertNode(5, comparator)
bstree.InsertNode(2, comparator)
bstree.InsertNode(4, comparator)
acturl := bstree.InOrderTraverse()
t.Log(acturl)
assert.Equal([]int{2, 4, 5, 6, 7}, acturl)
}
func TestBSTree_LevelOrderTraverse(t *testing.T) {
assert := internal.NewAssert(t, "TestBSTree_LevelOrderTraverse")
bstree := NewBSTree(6)
comparator := &intComparator{}
bstree.InsertNode(7, comparator)
bstree.InsertNode(5, comparator)
bstree.InsertNode(2, comparator)
bstree.InsertNode(4, comparator)
bstree.Print()
acturl := bstree.LevelOrderTraverse()
t.Log(acturl)
assert.Equal([]int{6, 5, 7, 2, 4}, acturl)
}
func TestBSTree_DeletetNode(t *testing.T) {
assert := internal.NewAssert(t, "TestBSTree_DeletetNode")
bstree := NewBSTree(6)
comparator := &intComparator{}
bstree.InsertNode(7, comparator)
bstree.InsertNode(5, comparator)
bstree.InsertNode(2, comparator)
bstree.InsertNode(4, comparator)
bstree.Print()
bstree.DeletetNode(4, comparator)
bstree.Print()
acturl1 := bstree.InOrderTraverse()
t.Log(acturl1)
assert.Equal([]int{2, 5, 6, 7}, acturl1)
//todo
// bstree.DeletetNode(6, comparator)
// bstree.Print()
// acturl2 := bstree.InOrderTraverse()
// t.Log(acturl2)
// assert.Equal([]int{2, 5, 7}, acturl2)
}
func TestBSTree_Depth(t *testing.T) {
assert := internal.NewAssert(t, "TestBSTree_Depth")
bstree := NewBSTree(6)
comparator := &intComparator{}
bstree.InsertNode(7, comparator)
bstree.InsertNode(5, comparator)
bstree.InsertNode(2, comparator)
bstree.InsertNode(4, comparator)
bstree.Print()
assert.Equal(bstree.Depth(), 4)
}

View File

@@ -0,0 +1,224 @@
package datastructure
import (
"fmt"
"math"
"github.com/duke-git/lancet/v2/datastructure"
"github.com/duke-git/lancet/v2/lancetconstraints"
)
func preOrderTraverse[T any](node *datastructure.TreeNode[T]) []T {
data := []T{}
if node != nil {
data = append(data, node.Data)
data = append(data, preOrderTraverse(node.Left)...)
data = append(data, preOrderTraverse(node.Right)...)
}
return data
}
func postOrderTraverse[T any](node *datastructure.TreeNode[T]) []T {
data := []T{}
if node != nil {
data = append(data, preOrderTraverse(node.Left)...)
data = append(data, preOrderTraverse(node.Right)...)
data = append(data, node.Data)
}
return data
}
func inOrderTraverse[T any](node *datastructure.TreeNode[T]) []T {
data := []T{}
if node != nil {
data = append(data, inOrderTraverse(node.Left)...)
data = append(data, node.Data)
data = append(data, inOrderTraverse(node.Right)...)
}
return data
}
func preOrderPrint[T any](node *datastructure.TreeNode[T]) {
if node == nil {
return
}
fmt.Printf("%v, ", node.Data)
preOrderPrint(node.Left)
preOrderPrint(node.Right)
}
func postOrderPrint[T any](node *datastructure.TreeNode[T]) {
if node == nil {
return
}
preOrderPrint(node.Left)
preOrderPrint(node.Right)
fmt.Printf("%v, ", node.Data)
}
func inOrderPrint[T any](node *datastructure.TreeNode[T]) {
if node == nil {
return
}
inOrderPrint(node.Left)
fmt.Printf("%v, ", node.Data)
inOrderPrint(node.Right)
}
func levelOrderTraverse[T any](root *datastructure.TreeNode[T], traversal *[]T) {
var q []*datastructure.TreeNode[T] // queue
var n *datastructure.TreeNode[T] // temp node
q = append(q, root)
for len(q) != 0 {
n, q = q[0], q[1:]
*traversal = append(*traversal, n.Data)
if n.Left != nil {
q = append(q, n.Left)
}
if n.Right != nil {
q = append(q, n.Right)
}
}
}
func insertTreeNode[T any](rootNode, newNode *datastructure.TreeNode[T], comparator lancetconstraints.Comparator) {
if comparator.Compare(newNode.Data, rootNode.Data) == -1 {
if rootNode.Left == nil {
rootNode.Left = newNode
} else {
insertTreeNode(rootNode.Left, newNode, comparator)
}
} else {
if rootNode.Right == nil {
rootNode.Right = newNode
} else {
insertTreeNode(rootNode.Right, newNode, comparator)
}
}
}
// todo, delete root node failed
func deleteTreeNode[T any](node *datastructure.TreeNode[T], data T, comparator lancetconstraints.Comparator) *datastructure.TreeNode[T] {
if node == nil {
return nil
}
if comparator.Compare(data, node.Data) == -1 {
node.Left = deleteTreeNode(node.Left, data, comparator)
} else if comparator.Compare(data, node.Data) == 1 {
node.Right = deleteTreeNode(node.Right, data, comparator)
} else {
if node.Left == nil {
node = node.Right
} else if node.Right == nil {
node = node.Left
} else {
l := node.Right
d := inOrderSuccessor(l)
d.Left = node.Left
return node.Right
}
}
return node
}
func inOrderSuccessor[T any](root *datastructure.TreeNode[T]) *datastructure.TreeNode[T] {
cur := root
for cur.Left != nil {
cur = cur.Left
}
return cur
}
func printTreeNodes[T any](nodes []*datastructure.TreeNode[T], level, maxLevel int) {
if len(nodes) == 0 || isAllNil(nodes) {
return
}
floor := maxLevel - level
endgeLines := int(math.Pow(float64(2), (math.Max(float64(floor)-1, 0))))
firstSpaces := int(math.Pow(float64(2), float64(floor))) - 1
betweenSpaces := int(math.Pow(float64(2), float64(floor)+1)) - 1
printSpaces(firstSpaces)
newNodes := []*datastructure.TreeNode[T]{}
for _, node := range nodes {
if node != nil {
fmt.Printf("%v", node.Data)
newNodes = append(newNodes, node.Left)
newNodes = append(newNodes, node.Right)
} else {
newNodes = append(newNodes, nil)
newNodes = append(newNodes, nil)
printSpaces(1)
}
printSpaces(betweenSpaces)
}
fmt.Println("")
for i := 1; i <= endgeLines; i++ {
for j := 0; j < len(nodes); j++ {
printSpaces(firstSpaces - i)
if nodes[j] == nil {
printSpaces(endgeLines + endgeLines + i + 1)
continue
}
if nodes[j].Left != nil {
fmt.Print("/")
} else {
printSpaces(1)
}
printSpaces(i + i - 1)
if nodes[j].Right != nil {
fmt.Print("\\")
} else {
printSpaces(1)
}
printSpaces(endgeLines + endgeLines - 1)
}
fmt.Println("")
}
printTreeNodes(newNodes, level+1, maxLevel)
}
// printSpaces
func printSpaces(n int) {
for i := 0; i < n; i++ {
fmt.Print(" ")
}
}
func isAllNil[T any](nodes []*datastructure.TreeNode[T]) bool {
for _, v := range nodes {
if v != nil {
return false
}
}
return true
}
func calculateDepth[T any](node *datastructure.TreeNode[T], depth int) int {
if node == nil {
return depth
}
return max(calculateDepth(node.Left, depth+1), calculateDepth(node.Right, depth+1))
}
func max(a, b int) int {
if a > b {
return a
}
return b
}

60
datetime/conversion.go Normal file
View File

@@ -0,0 +1,60 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license.
package datetime
import "time"
type theTime struct {
unix int64
}
// NewUnixNow return unix timestamp of current time
func NewUnixNow() *theTime {
return &theTime{unix: time.Now().Unix()}
}
// NewUnix return unix timestamp of specified time
func NewUnix(unix int64) *theTime {
return &theTime{unix: unix}
}
// NewFormat return unix timestamp of specified time string, t should be "yyyy-mm-dd hh:mm:ss"
func NewFormat(t string) (*theTime, error) {
timeLayout := "2006-01-02 15:04:05"
loc := time.FixedZone("CST", 8*3600)
tt, err := time.ParseInLocation(timeLayout, t, loc)
if err != nil {
return nil, err
}
return &theTime{unix: tt.Unix()}, nil
}
// NewISO8601 return unix timestamp of specified iso8601 time string
func NewISO8601(iso8601 string) (*theTime, error) {
t, err := time.ParseInLocation(time.RFC3339, iso8601, time.UTC)
if err != nil {
return nil, err
}
return &theTime{unix: t.Unix()}, nil
}
// ToUnix return unix timestamp
func (t *theTime) ToUnix() int64 {
return t.unix
}
// ToFormat return the time string 'yyyy-mm-dd hh:mm:ss' of unix time
func (t *theTime) ToFormat() string {
return time.Unix(t.unix, 0).Format("2006-01-02 15:04:05")
}
// ToFormatForTpl return the time string which format is specified tpl
func (t *theTime) ToFormatForTpl(tpl string) string {
return time.Unix(t.unix, 0).Format(tpl)
}
// ToFormatForTpl return iso8601 time string
func (t *theTime) ToIso8601() string {
return time.Unix(t.unix, 0).Format(time.RFC3339)
}

View File

@@ -0,0 +1,53 @@
package datetime
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestToUnix(t *testing.T) {
assert := internal.NewAssert(t, "TestToUnix")
tm1 := NewUnixNow()
unixTimestamp := tm1.ToUnix()
tm2 := NewUnix(unixTimestamp)
assert.Equal(tm1, tm2)
}
func TestToFormat(t *testing.T) {
assert := internal.NewAssert(t, "TestToFormat")
_, err := NewFormat("2022/03/18 17:04:05")
assert.IsNotNil(err)
tm, err := NewFormat("2022-03-18 17:04:05")
assert.IsNil(err)
t.Log("ToFormat -> ", tm.ToFormat())
}
func TestToFormatForTpl(t *testing.T) {
assert := internal.NewAssert(t, "TestToFormatForTpl")
_, err := NewFormat("2022/03/18 17:04:05")
assert.IsNotNil(err)
tm, err := NewFormat("2022-03-18 17:04:05")
assert.IsNil(err)
t.Log("ToFormatForTpl -> ", tm.ToFormatForTpl("2006/01/02 15:04:05"))
}
func TestToIso8601(t *testing.T) {
assert := internal.NewAssert(t, "TestToIso8601")
_, err := NewISO8601("2022-03-18 17:04:05")
assert.IsNotNil(err)
tm, err := NewISO8601("2006-01-02T15:04:05.999Z")
assert.IsNil(err)
t.Log("ToIso8601 -> ", tm.ToIso8601())
}

View File

@@ -4,7 +4,7 @@ import (
"testing"
"time"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestAddDay(t *testing.T) {

593
docs/algorithm.md Normal file
View File

@@ -0,0 +1,593 @@
# Algorithm
Package algorithm implements some basic algorithm. eg. sort, search.
<div STYLE="page-break-after: always;"></div>
## Source
- [https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go](https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go)
- [https://github.com/duke-git/lancet/blob/main/algorithm/search.go](https://github.com/duke-git/lancet/blob/main/algorithm/search.go)
- [https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go)
<div STYLE="page-break-after: always;"></div>
## Usage
```go
import (
"github.com/duke-git/lancet/v2/algorithm"
)
```
<div STYLE="page-break-after: always;"></div>
## Index
- [BubbleSort](#BubbleSort)
- [CountSort](#CountSort)
- [HeapSort](#HeapSort)
- [InsertionSort](#InsertionSort)
- [MergeSort](#MergeSort)
- [QuickSort](#QuickSort)
- [SelectionSort](#SelectionSort)
- [ShellSort](#ShellSort)
- [BinarySearch](#BinarySearch)
- [BinaryIterativeSearch](#BinaryIterativeSearch)
- [LinearSearch](#LinearSearch)
- [LRUCache](#LRUCache)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="BubbleSort">BubbleSort</span>
<p>Sort slice with bubble sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.BubbleSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="InsertionSort">InsertionSort</span>
<p>Sort slice with insertion sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type people struct {
Name string
Age int
}
// PeopleAageComparator sort people slice by age field
type peopleAgeComparator struct{}
// Compare implements github.com/duke-git/lancet/lancetconstraints/constraints.go/Comparator
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
p1, _ := v1.(people)
p2, _ := v2.(people)
//ascending order
if p1.Age < p2.Age {
return -1
} else if p1.Age > p2.Age {
return 1
}
return 0
//decending order
// if p1.Age > p2.Age {
// return -1
// } else if p1.Age < p2.Age {
// return 1
// }
}
var peoples = []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
sortedPeople := algorithm.InsertionSort(peoples, comparator)
fmt.Println(sortedSlice) //[{d 8} {b 10} {c 17} {a 20} {e 28}]
}
```
### <span id="SelectionSort">SelectionSort</span>
<p>Sort slice with selection sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.SelectionSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="ShellSort">ShellSort</span>
<p>Sort slice with shell sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.ShellSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="QuickSort">QuickSort</span>
<p>Sort slice with quick sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.QuickSort(intSlice, 0, len(intSlice)-1, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="HeapSort">HeapSort</span>
<p>Sort slice with heap sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.HeapSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="MergeSort">MergeSort</span>
<p>Sort slice with merge sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func MergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.MergeSort(intSlice, 0, len(intSlice)-1, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="CountSort">CountSort</span>
<p>Sort slice with count sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.CountSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="BinarySearch">BinarySearch</span>
<p>BinarySearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.</p>
<b>Signature:</b>
```go
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
foundIndex := algorithm.BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
fmt.Println(notFoundIndex) //-1
}
```
### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span>
<p>BinaryIterativeSearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.</p>
<b>Signature:</b>
```go
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
foundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
fmt.Println(notFoundIndex) //-1
}
```
### <span id="LinearSearch">LinearSearch</span>
<p>LinearSearch Simple linear search algorithm that iterates over all elements of an slice. If a target is found, the index of the target is returned. Else the function return -1.</p>
<b>Signature:</b>
```go
func LinearSearch[T any](slice []T, target T, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
foundIndex := algorithm.LinearSearch(intSlice, 5, comparator)
fmt.Println(foundIndex) //2
notFoundIndex := algorithm.LinearSearch(sortedNumbers, 0, comparator)
fmt.Println(notFoundIndex) //-1
}
```
### <span id="LRUCache">LRUCache</span>
<p>LRUCache implements mem cache with lru.</p>
<b>Signature:</b>
```go
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V]
func (l *LRUCache[K, V]) Get(key K) (V, bool)
func (l *LRUCache[K, V]) Put(key K, value V)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
cache := algorithm.NewLRUCache[int, int](2)
cache.Put(1, 1)
cache.Put(2, 2)
_, ok := cache.Get(0) // ok -> false
v, ok := cache.Get(1) // v->1, ok->true
}
```

593
docs/algorithm_zh-CN.md Normal file
View File

@@ -0,0 +1,593 @@
# Algorithm
algorithm算法包实现一些基本算法sortsearchlrucache。
<div STYLE="page-break-after: always;"></div>
## 源码
- [https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go](https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go)
- [https://github.com/duke-git/lancet/blob/main/algorithm/search.go](https://github.com/duke-git/lancet/blob/main/algorithm/search.go)
- [https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go)
<div STYLE="page-break-after: always;"></div>
## 用法
```go
import (
"github.com/duke-git/lancet/v2/algorithm"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [BubbleSort](#BubbleSort)
- [CountSort](#CountSort)
- [HeapSort](#HeapSort)
- [InsertionSort](#InsertionSort)
- [MergeSort](#MergeSort)
- [QuickSort](#QuickSort)
- [SelectionSort](#SelectionSort)
- [ShellSort](#ShellSort)
- [BinarySearch](#BinarySearch)
- [BinaryIterativeSearch](#BinaryIterativeSearch)
- [LinearSearch](#LinearSearch)
- [LRUCache](#LRUCache)
<div STYLE="page-break-after: always;"></div>
## 文档
### <span id="BubbleSort">BubbleSort</span>
<p>冒泡排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.BubbleSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="InsertionSort">InsertionSort</span>
<p>插入排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type people struct {
Name string
Age int
}
// PeopleAageComparator sort people slice by age field
type peopleAgeComparator struct{}
// Compare implements github.com/duke-git/lancet/lancetconstraints/constraints.go/Comparator
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
p1, _ := v1.(people)
p2, _ := v2.(people)
//ascending order
if p1.Age < p2.Age {
return -1
} else if p1.Age > p2.Age {
return 1
}
return 0
//decending order
// if p1.Age > p2.Age {
// return -1
// } else if p1.Age < p2.Age {
// return 1
// }
}
var peoples = []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
sortedPeople := algorithm.InsertionSort(peoples, comparator)
fmt.Println(sortedSlice) //[{d 8} {b 10} {c 17} {a 20} {e 28}]
}
```
### <span id="SelectionSort">SelectionSort</span>
<p>选择排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.SelectionSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="ShellSort">ShellSort</span>
<p>希尔排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.ShellSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="QuickSort">QuickSort</span>
<p>快速排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.QuickSort(intSlice, 0, len(intSlice)-1, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="HeapSort">HeapSort</span>
<p>堆排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.HeapSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="MergeSort">MergeSort</span>
<p>归并排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func MergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.MergeSort(intSlice, 0, len(intSlice)-1, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="CountSort">CountSort</span>
<p>计数排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.CountSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="BinarySearch">BinarySearch</span>
<p>二分递归查找,返回元素索引,未找到元素返回-1参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
foundIndex := algorithm.BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
fmt.Println(notFoundIndex) //-1
}
```
### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span>
<p>二分迭代查找,返回元素索引,未找到元素返回-1参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
foundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
fmt.Println(notFoundIndex) //-1
}
```
### <span id="LinearSearch">LinearSearch</span>
<p>线性查找,返回元素索引,未找到元素返回-1参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func LinearSearch[T any](slice []T, target T, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
foundIndex := algorithm.LinearSearch(intSlice, 5, comparator)
fmt.Println(foundIndex) //2
notFoundIndex := algorithm.LinearSearch(sortedNumbers, 0, comparator)
fmt.Println(notFoundIndex) //-1
}
```
### <span id="LRUCache">LRUCache</span>
<p>lru实现缓存</p>
<b>函数签名:</b>
```go
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V]
func (l *LRUCache[K, V]) Get(key K) (V, bool)
func (l *LRUCache[K, V]) Put(key K, value V)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
cache := algorithm.NewLRUCache[int, int](2)
cache.Put(1, 1)
cache.Put(2, 2)
_, ok := cache.Get(0) // ok -> false
v, ok := cache.Get(1) // v->1, ok->true
}
```

View File

@@ -5,14 +5,14 @@ Package convertor contains some functions for data type convertion.
## Source:
[https://github.com/duke-git/lancet/blob/main/convertor/convertor.go](https://github.com/duke-git/lancet/blob/main/convertor/convertor.go)
- [https://github.com/duke-git/lancet/blob/main/convertor/convertor.go](https://github.com/duke-git/lancet/blob/main/convertor/convertor.go)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
```
@@ -50,12 +50,12 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
colorHex := "#003366"
r, g, b := ColorHexToRGB(colorHex)
r, g, b := convertor.ColorHexToRGB(colorHex)
fmt.Println(r, g, b) //0,51,102
}
```
@@ -78,14 +78,14 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
r := 0
g := 51
b := 102
colorHex := ColorRGBToHex(r, g, b)
colorHex := convertor.ColorRGBToHex(r, g, b)
fmt.Println(colorHex) //#003366
}
@@ -109,7 +109,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -136,7 +136,7 @@ func main() {
<b>Signature:</b>
```go
func ToBytes(data interface{}) ([]byte, error)
func ToBytes(data any) ([]byte, error)
```
<b>Example:</b>
@@ -145,7 +145,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -175,7 +175,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -199,7 +199,7 @@ func main() {
<b>Signature:</b>
```go
func ToFloat(value interface{}) (float64, error)
func ToFloat(value any) (float64, error)
```
<b>Example:</b>
@@ -208,7 +208,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -232,7 +232,7 @@ func main() {
<b>Signature:</b>
```go
func ToInt(value interface{}) (int64, error)
func ToInt(value any) (int64, error)
```
<b>Example:</b>
@@ -241,7 +241,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -265,7 +265,7 @@ func main() {
<b>Signature:</b>
```go
func ToJson(value interface{}) (string, error)
func ToJson(value any) (string, error)
```
<b>Example:</b>
@@ -274,7 +274,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -293,7 +293,7 @@ func main() {
<b>Signature:</b>
```go
func ToString(value interface{}) string
func ToString(value any) string
```
<b>Example:</b>
@@ -302,7 +302,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -321,7 +321,7 @@ func main() {
<b>Signature:</b>
```go
func StructToMap(value interface{}) (map[string]interface{}, error)
func StructToMap(value any) (map[string]any, error)
```
<b>Example:</b>
@@ -330,7 +330,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {

View File

@@ -5,7 +5,7 @@ convertor转换器包支持一些常见的数据类型转换
## 源码:
[https://github.com/duke-git/lancet/blob/main/convertor/convertor.go](https://github.com/duke-git/lancet/blob/main/convertor/convertor.go)
- [https://github.com/duke-git/lancet/blob/main/convertor/convertor.go](https://github.com/duke-git/lancet/blob/main/convertor/convertor.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ convertor转换器包支持一些常见的数据类型转换
```go
import (
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
```
@@ -52,12 +52,12 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
colorHex := "#003366"
r, g, b := ColorHexToRGB(colorHex)
r, g, b := convertor.ColorHexToRGB(colorHex)
fmt.Println(r, g, b) //0,51,102
}
```
@@ -80,14 +80,14 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
r := 0
g := 51
b := 102
colorHex := ColorRGBToHex(r, g, b)
colorHex := convertor.ColorRGBToHex(r, g, b)
fmt.Println(colorHex) //#003366
}
@@ -111,7 +111,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -138,7 +138,7 @@ func main() {
<b>函数签名:</b>
```go
func ToBytes(data interface{}) ([]byte, error)
func ToBytes(data any) ([]byte, error)
```
<b>列子:</b>
@@ -147,7 +147,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -177,7 +177,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -201,7 +201,7 @@ func main() {
<b>函数签名:</b>
```go
func ToFloat(value interface{}) (float64, error)
func ToFloat(value any) (float64, error)
```
<b>列子:</b>
@@ -210,7 +210,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -234,7 +234,7 @@ func main() {
<b>函数签名:</b>
```go
func ToInt(value interface{}) (int64, error)
func ToInt(value any) (int64, error)
```
<b>例子:</b>
@@ -243,7 +243,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -267,7 +267,7 @@ func main() {
<b>函数签名:</b>
```go
func ToJson(value interface{}) (string, error)
func ToJson(value any) (string, error)
```
<b>列子:</b>
@@ -276,7 +276,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -295,7 +295,7 @@ func main() {
<b>函数签名:</b>
```go
func ToString(value interface{}) string
func ToString(value any) string
```
<b>例子:</b>
@@ -304,7 +304,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
@@ -323,7 +323,7 @@ func main() {
<b>函数签名:</b>
```go
func StructToMap(value interface{}) (map[string]interface{}, error)
func StructToMap(value any) (map[string]any, error)
```
<b>列子:</b>
@@ -332,7 +332,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {

View File

@@ -15,7 +15,7 @@ Package cryptor contains some functions for data encryption and decryption. Supp
## Usage:
```go
import (
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
```
@@ -80,7 +80,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -110,7 +110,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -140,7 +140,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -171,7 +171,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -202,7 +202,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -234,7 +234,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -264,7 +264,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -295,7 +295,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -325,7 +325,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -356,7 +356,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -384,7 +384,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -412,7 +412,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -443,7 +443,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -475,7 +475,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -506,7 +506,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -538,7 +538,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -570,7 +570,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -600,7 +600,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -631,7 +631,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -661,7 +661,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -693,7 +693,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -721,7 +721,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -749,7 +749,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -777,7 +777,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -806,7 +806,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -834,7 +834,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -862,7 +862,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -890,7 +890,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -918,7 +918,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -946,7 +946,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -976,7 +976,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -1012,7 +1012,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {

View File

@@ -15,7 +15,7 @@ cryptor加密包支持数据加密和解密获取md5hash值。支持base64
## 用法:
```go
import (
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
```
@@ -80,7 +80,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -110,7 +110,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -140,7 +140,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -171,7 +171,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -203,7 +203,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -235,7 +235,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -265,7 +265,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -296,7 +296,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -326,7 +326,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -356,7 +356,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -384,7 +384,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -412,7 +412,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -443,7 +443,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -475,7 +475,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -506,7 +506,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -538,7 +538,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -570,7 +570,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -600,7 +600,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -631,7 +631,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -661,7 +661,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -692,7 +692,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -720,7 +720,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -748,7 +748,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -776,7 +776,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -805,7 +805,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -833,7 +833,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -861,7 +861,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -889,7 +889,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -917,7 +917,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -945,7 +945,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -975,7 +975,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
@@ -1009,7 +1009,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/cryptor"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {

View File

@@ -5,14 +5,15 @@ Package datetime supports date and time format and compare.
## Source:
[https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go)
- [https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go)
- [https://github.com/duke-git/lancet/blob/main/datetime/conversion.go](https://github.com/duke-git/lancet/blob/main/datetime/conversion.go)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
```
@@ -28,7 +29,6 @@ import (
- [BeginOfWeek](#BeginOfWeek)
- [BeginOfMonth](#BeginOfMonth)
- [BeginOfYear](#BeginOfYear)
- [EndOfMinute](#EndOfMinute)
- [EndOfHour](#EndOfHour)
- [EndOfDay](#EndOfDay)
@@ -41,9 +41,19 @@ import (
- [GetZeroHourTimestamp](#GetZeroHourTimestamp)
- [GetNightTimestamp](#GetNightTimestamp)
- [FormatTimeToStr](#FormatTimeToStr)
- [FormatStrToTime](#FormatStrToTime)
- [NewUnixNow](#NewUnixNow)
- [NewUnix](#NewUnix)
- [NewFormat](#NewFormat)
- [NewISO8601](#NewISO8601)
- [ToUnix](#ToUnix)
- [ToFormat](#ToFormat)
- [ToFormatForTpl](#ToFormatForTpl)
- [ToIso8601](#ToIso8601)
<div STYLE="page-break-after: always;"></div>
## Documentation
@@ -86,7 +96,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -115,7 +125,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -143,7 +153,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -171,7 +181,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -197,7 +207,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -223,7 +233,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -251,7 +261,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -279,7 +289,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -306,7 +316,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -334,7 +344,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -360,7 +370,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -386,7 +396,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -414,7 +424,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -442,7 +452,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -469,7 +479,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -496,7 +506,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -523,7 +533,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -550,7 +560,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -577,7 +587,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -604,7 +614,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -630,7 +640,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -656,7 +666,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -667,3 +677,221 @@ func main() {
### <span id="NewUnixNow">NewUnixNow</span>
<p>Return unix timestamp of current time</p>
<b>Signature:</b>
```go
type theTime struct {
unix int64
}
func NewUnixNow() *theTime
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm) //&{1647597438}
}
```
### <span id="NewUnix">NewUnix</span>
<p>Return unix timestamp of specified int64 value.</p>
<b>Signature:</b>
```go
type theTime struct {
unix int64
}
func NewUnix(unix int64) *theTime
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnix(1647597438)
fmt.Println(tm) //&{1647597438}
}
```
### <span id="NewFormat">NewFormat</span>
<p>Return unix timestamp of specified time string, t should be "yyyy-mm-dd hh:mm:ss".</p>
<b>Signature:</b>
```go
type theTime struct {
unix int64
}
func NewFormat(t string) (*theTime, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, err := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm) //&{1647594245}
}
```
### <span id="NewISO8601">NewISO8601</span>
<p>Return unix timestamp of specified iso8601 time string.</p>
<b>Signature:</b>
```go
type theTime struct {
unix int64
}
func NewISO8601(iso8601 string) (*theTime, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, err := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
fmt.Println(tm) //&{1136214245}
}
```
### <span id="ToUnix">ToUnix</span>
<p>Return unix timestamp.</p>
<b>Signature:</b>
```go
func (t *theTime) ToUnix() int64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm.ToUnix()) //1647597438
}
```
### <span id="ToFormat">ToFormat</span>
<p>Return time string 'yyyy-mm-dd hh:mm:ss'.</p>
<b>Signature:</b>
```go
func (t *theTime) ToFormat() string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm.ToFormat()) //"2022-03-18 17:04:05"
}
```
### <span id="ToFormatForTpl">ToFormatForTpl</span>
<p>Return the time string which format is specified tpl.</p>
<b>Signature:</b>
```go
func (t *theTime) ToFormatForTpl(tpl string) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
ts := tm.ToFormatForTpl("2006/01/02 15:04:05")
fmt.Println(ts) //"2022/03/18 17:04:05"
}
```
### <span id="ToIso8601">ToIso8601</span>
<p>Return iso8601 time string.</p>
<b>Signature:</b>
```go
func (t *theTime) ToIso8601() string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
ts := tm.ToIso8601()
fmt.Println(ts) //"2006-01-02T23:04:05+08:00"
}
```

View File

@@ -5,14 +5,14 @@ datetime日期时间处理包格式化日期比较日期。
## 源码:
[https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go)
- [https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
```
@@ -28,7 +28,6 @@ import (
- [BeginOfWeek](#BeginOfWeek)
- [BeginOfMonth](#BeginOfMonth)
- [BeginOfYear](#BeginOfYear)
- [EndOfMinute](#EndOfMinute)
- [EndOfHour](#EndOfHour)
- [EndOfDay](#EndOfDay)
@@ -43,6 +42,15 @@ import (
- [FormatTimeToStr](#FormatTimeToStr)
- [FormatStrToTime](#FormatStrToTime)
- [NewUnixNow](#NewUnixNow)
- [NewUnix](#NewUnix)
- [NewFormat](#NewFormat)
- [NewISO8601](#NewISO8601)
- [ToUnix](#ToUnix)
- [ToFormat](#ToFormat)
- [ToFormatForTpl](#ToFormatForTpl)
- [ToIso8601](#ToIso8601)
<div STYLE="page-break-after: always;"></div>
## 文档
@@ -85,7 +93,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -114,7 +122,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -142,7 +150,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -170,7 +178,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -196,7 +204,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -222,7 +230,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -250,7 +258,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -278,7 +286,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -305,7 +313,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -333,7 +341,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -359,7 +367,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -385,7 +393,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -413,7 +421,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -441,7 +449,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -468,7 +476,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -495,7 +503,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -522,7 +530,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -549,7 +557,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -576,7 +584,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -603,7 +611,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -629,7 +637,7 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -655,7 +663,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/datetime"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
@@ -665,4 +673,221 @@ func main() {
```
### <span id="NewUnixNow">NewUnixNow</span>
<p>创建一个当前时间的unix时间戳</p>
<b>函数签名:</b>
```go
type theTime struct {
unix int64
}
func NewUnixNow() *theTime
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm) //&{1647597438}
}
```
### <span id="NewUnix">NewUnix</span>
<p>创建一个unix时间戳</p>
<b>函数签名:</b>
```go
type theTime struct {
unix int64
}
func NewUnix(unix int64) *theTime
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnix(1647597438)
fmt.Println(tm) //&{1647597438}
}
```
### <span id="NewFormat">NewFormat</span>
<p>创建一个yyyy-mm-dd hh:mm:ss格式时间字符串的unix时间戳</p>
<b>函数签名:</b>
```go
type theTime struct {
unix int64
}
func NewFormat(t string) (*theTime, error)
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, err := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm) //&{1647594245}
}
```
### <span id="NewISO8601">NewISO8601</span>
<p>创建一个iso8601格式时间字符串的unix时间戳</p>
<b>函数签名:</b>
```go
type theTime struct {
unix int64
}
func NewISO8601(iso8601 string) (*theTime, error)
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, err := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
fmt.Println(tm) //&{1136214245}
}
```
### <span id="ToUnix">ToUnix</span>
<p>返回unix时间戳</p>
<b>函数签名:</b>
```go
func (t *theTime) ToUnix() int64
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm.ToUnix()) //1647597438
}
```
### <span id="ToFormat">ToFormat</span>
<p>返回格式'yyyy-mm-dd hh:mm:ss'的日期字符串</p>
<b>函数签名:</b>
```go
func (t *theTime) ToFormat() string
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm.ToFormat()) //"2022-03-18 17:04:05"
}
```
### <span id="ToFormatForTpl">ToFormatForTpl</span>
<p>返回tpl格式指定的日期字符串</p>
<b>函数签名:</b>
```go
func (t *theTime) ToFormatForTpl(tpl string) string
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
ts := tm.ToFormatForTpl("2006/01/02 15:04:05")
fmt.Println(ts) //"2022/03/18 17:04:05"
}
```
### <span id="ToIso8601">ToIso8601</span>
<p>返回iso8601日期字符串</p>
<b>函数签名:</b>
```go
func (t *theTime) ToIso8601() string
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
ts := tm.ToIso8601()
fmt.Println(ts) //"2006-01-02T23:04:05+08:00"
}
```

View File

@@ -5,14 +5,14 @@ Package fileutil implements some basic functions for file operations.
## Source:
[https://github.com/duke-git/lancet/blob/main/fileutil/file.go](https://github.com/duke-git/lancet/blob/main/fileutil/file.go)
- [https://github.com/duke-git/lancet/blob/main/fileutil/file.go](https://github.com/duke-git/lancet/blob/main/fileutil/file.go)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
```
@@ -56,7 +56,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -82,7 +82,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -107,7 +107,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -135,7 +135,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -155,7 +155,7 @@ func main() {
<b>Signature:</b>
```go
func MiMeType(file interface{}) string
func MiMeType(file any) string
```
<b>Example:</b>
@@ -165,7 +165,7 @@ package main
import (
"fmt"
"os"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -196,7 +196,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -223,7 +223,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -249,7 +249,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -278,7 +278,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -304,7 +304,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -332,7 +332,7 @@ package main
import (
"fmt"
"os"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -365,7 +365,7 @@ package main
import (
"fmt"
"os"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -398,7 +398,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -427,7 +427,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {

View File

@@ -5,14 +5,14 @@ fileutil包支持文件基本操作。
## 源码:
[https://github.com/duke-git/lancet/blob/main/fileutil/file.go](https://github.com/duke-git/lancet/blob/main/fileutil/file.go)
- [https://github.com/duke-git/lancet/blob/main/fileutil/file.go](https://github.com/duke-git/lancet/blob/main/fileutil/file.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
```
@@ -56,7 +56,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -82,7 +82,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -107,7 +107,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -135,7 +135,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -155,7 +155,7 @@ func main() {
<b>函数签名:</b>
```go
func MiMeType(file interface{}) string
func MiMeType(file any) string
```
<b>例子:</b>
@@ -165,7 +165,7 @@ package main
import (
"fmt"
"os"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -196,7 +196,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -223,7 +223,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -249,7 +249,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -278,7 +278,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -304,7 +304,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -332,7 +332,7 @@ package main
import (
"fmt"
"os"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -365,7 +365,7 @@ package main
import (
"fmt"
"os"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -398,7 +398,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
@@ -427,7 +427,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {

View File

@@ -5,14 +5,14 @@ formatter contains some functions for data formatting.
## Source:
[https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
- [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/formatter"
"github.com/duke-git/lancet/v2/formatter"
)
```
@@ -34,7 +34,7 @@ Param should be number or numberic string.</p>
<b>Signature:</b>
```go
func Comma(v interface{}, symbol string) string
func Comma(v any, symbol string) string
```
<b>Example:</b>
@@ -43,7 +43,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/formatter"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {

View File

@@ -5,14 +5,14 @@ formatter格式化器包含一些数据格式化处理方法。
## 源码:
[https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
- [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/formatter"
"github.com/duke-git/lancet/v2/formatter"
)
```
@@ -33,7 +33,7 @@ import (
<b>函数签名:</b>
```go
func Comma(v interface{}, symbol string) string
func Comma(v any, symbol string) string
```
<b>例子:</b>
@@ -42,7 +42,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/formatter"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {

View File

@@ -5,15 +5,15 @@ Package function can control the flow of function execution and support part of
## Source:
[https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go)
[https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go)
- [https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go)
- [https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
```
@@ -40,7 +40,7 @@ import (
<b>Signature:</b>
```go
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value
func After(n int, fn any) func(args ...any) []reflect.Value
```
<b>Example:</b>
@@ -49,7 +49,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {
@@ -59,7 +59,7 @@ func main() {
return i
})
type cb func(args ...interface{}) []reflect.Value
type cb func(args ...any) []reflect.Value
print := func(i int, s string, fn cb) {
fmt.Printf("arr[%d] is %s \n", i, s)
fn(i)
@@ -87,7 +87,7 @@ func main() {
<b>Signature:</b>
```go
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value
func Before(n int, fn any) func(args ...any) []reflect.Value
```
<b>Example:</b>
@@ -96,8 +96,8 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/function"
"github.com/duke-git/lancet/v2/internal"
)
func main() {
@@ -109,7 +109,7 @@ func main() {
})
var res []int64
type cb func(args ...interface{}) []reflect.Value
type cb func(args ...any) []reflect.Value
appendStr := func(i int, s string, fn cb) {
v := fn(i)
res = append(res, v[0].Int())
@@ -133,8 +133,8 @@ func main() {
<b>Signature:</b>
```go
type Fn func(...interface{}) interface{}
func (f Fn) Curry(i interface{}) func(...interface{}) interface{}
type Fn func(...any) any
func (f Fn) Curry(i any) func(...any) any
```
<b>Example:</b>
@@ -143,14 +143,14 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {
add := func(a, b int) int {
return a + b
}
var addCurry function.Fn = func(values ...interface{}) interface{} {
var addCurry function.Fn = func(values ...any) any {
return add(values[0].(int), values[1].(int))
}
add1 := addCurry.Curry(1)
@@ -168,7 +168,7 @@ func main() {
<b>Signature:</b>
```go
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{}
func Compose(fnList ...func(...any) any) func(...any) any
```
<b>Example:</b>
@@ -177,14 +177,14 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {
add1 := func(v ...interface{}) interface{} {
add1 := func(v ...any) any {
return v[0].(int) + 1
}
add2 := func(v ...interface{}) interface{} {
add2 := func(v ...any) any {
return v[0].(int) + 2
}
@@ -213,7 +213,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {
@@ -246,7 +246,7 @@ func main() {
<b>Signature:</b>
```go
func Delay(delay time.Duration, fn interface{}, args ...interface{})
func Delay(delay time.Duration, fn any, args ...any)
```
<b>Example:</b>
@@ -255,7 +255,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {
@@ -275,7 +275,7 @@ func main() {
<b>Signature:</b>
```go
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool
func Schedule(d time.Duration, fn any, args ...any) chan bool
```
<b>Example:</b>
@@ -284,7 +284,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {
@@ -327,7 +327,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {

View File

@@ -5,15 +5,15 @@ function函数包控制函数执行流程包含部分函数式编程。
## 源码:
[https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go)
[https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go)
- [https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go)
- [https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
```
@@ -40,7 +40,7 @@ import (
<b>函数签名:</b>
```go
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value
func After(n int, fn any) func(args ...any) []reflect.Value
```
<b>例子:</b>
@@ -49,7 +49,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {
@@ -59,7 +59,7 @@ func main() {
return i
})
type cb func(args ...interface{}) []reflect.Value
type cb func(args ...any) []reflect.Value
print := func(i int, s string, fn cb) {
fmt.Printf("arr[%d] is %s \n", i, s)
fn(i)
@@ -87,7 +87,7 @@ func main() {
<b>函数签名:</b>
```go
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value
func Before(n int, fn any) func(args ...any) []reflect.Value
```
<b>例子:</b>
@@ -96,8 +96,8 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/function"
"github.com/duke-git/lancet/v2/internal"
)
func main() {
@@ -109,7 +109,7 @@ func main() {
})
var res []int64
type cb func(args ...interface{}) []reflect.Value
type cb func(args ...any) []reflect.Value
appendStr := func(i int, s string, fn cb) {
v := fn(i)
res = append(res, v[0].Int())
@@ -133,8 +133,8 @@ func main() {
<b>函数签名:</b>
```go
type Fn func(...interface{}) interface{}
func (f Fn) Curry(i interface{}) func(...interface{}) interface{}
type Fn func(...any) any
func (f Fn) Curry(i any) func(...any) any
```
<b>例子:</b>
@@ -143,14 +143,14 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {
add := func(a, b int) int {
return a + b
}
var addCurry function.Fn = func(values ...interface{}) interface{} {
var addCurry function.Fn = func(values ...any) any {
return add(values[0].(int), values[1].(int))
}
add1 := addCurry.Curry(1)
@@ -168,7 +168,7 @@ func main() {
<b>函数签名:</b>
```go
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{}
func Compose(fnList ...func(...any) any) func(...any) any
```
<b>例子:</b>
@@ -177,14 +177,14 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {
add1 := func(v ...interface{}) interface{} {
add1 := func(v ...any) any {
return v[0].(int) + 1
}
add2 := func(v ...interface{}) interface{} {
add2 := func(v ...any) any {
return v[0].(int) + 2
}
@@ -213,7 +213,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {
@@ -246,7 +246,7 @@ func main() {
<b>函数签名:</b>
```go
func Delay(delay time.Duration, fn interface{}, args ...interface{})
func Delay(delay time.Duration, fn any, args ...any)
```
<b>例子:</b>
@@ -255,7 +255,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {
@@ -275,7 +275,7 @@ func main() {
<b>函数签名:</b>
```go
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool
func Schedule(d time.Duration, fn any, args ...any) chan bool
```
<b>例子:</b>
@@ -284,7 +284,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {
@@ -327,7 +327,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/function"
"github.com/duke-git/lancet/v2/function"
)
func main() {

304
docs/maputil.md Normal file
View File

@@ -0,0 +1,304 @@
# Maputil
Package maputil includes some functions to manipulate map.
<div STYLE="page-break-after: always;"></div>
## Source:
- [https://github.com/duke-git/lancet/blob/main/maputil/maputil.go](https://github.com/duke-git/lancet/blob/main/maputil/maputil.go)
<div STYLE="page-break-after: always;"></div>
## Example:
```go
import (
"github.com/duke-git/lancet/v2/maputil"
)
```
<div STYLE="page-break-after: always;"></div>
## Index
- [ForEach](#ForEach)
- [Filter](#Filter)
- [Intersect](#Intersect)
- [Keys](#Keys)
- [Merge](#Merge)
- [Minus](#Minus)
- [Values](#Values)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="ForEach">ForEach</span>
<p>Executes iteratee funcation for every key and value pair in map.</p>
<b>Signature:</b>
```go
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V))
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
}
var sum int
maputil.ForEach(m, func(_ string, value int) {
sum += value
})
fmt.Println(sum) // 10
}
```
### <span id="Filter">Filter</span>
<p>Iterates over map, return a new map contains all key and value pairs pass the predicate function.</p>
<b>Signature:</b>
```go
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
isEven := func(_ string, value int) bool {
return value%2 == 0
}
maputil.Filter(m, func(_ string, value int) {
sum += value
})
res := maputil.Filter(m, isEven)
fmt.Println(res) // map[string]int{"b": 2, "d": 4,}
}
```
### <span id="Intersect">Intersect</span>
<p>Iterates over maps, return a new map of key and value pairs in all given maps.</p>
<b>Signature:</b>
```go
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[string]int{
"a": 1,
"b": 2,
"c": 6,
"d": 7,
}
m3 := map[string]int{
"a": 1,
"b": 9,
"e": 9,
}
fmt.Println(maputil.Intersect(m1)) // map[string]int{"a": 1, "b": 2, "c": 3}
fmt.Println(maputil.Intersect(m1, m2)) // map[string]int{"a": 1, "b": 2}
fmt.Println(maputil.Intersect(m1, m2, m3)) // map[string]int{"a": 1}
}
```
### <span id="Keys">Keys</span>
<p>Returns a slice of the map's keys.</p>
<b>Signature:</b>
```go
func Keys[K comparable, V any](m map[K]V) []K
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
}
keys := maputil.Keys(m)
sort.Ints(keys)
fmt.Println(keys) // []int{1, 2, 3, 4, 5}
}
```
### <span id="Merge">Merge</span>
<p>Merge maps, next key will overwrite previous key.</p>
<b>Signature:</b>
```go
func Merge[K comparable, V any](maps ...map[K]V) map[K]V
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m1 := map[int]string{
1: "a",
2: "b",
}
m2 := map[int]string{
1: "1",
3: "2",
}
fmt.Println(maputil.Merge(m1, m2)) // map[int]string{1:"1", 2:"b", 3:"2",}
}
```
### <span id="Minus">Minus</span>
<p>Creates an map of whose key in mapA but not in mapB.</p>
<b>Signature:</b>
```go
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[string]int{
"a": 11,
"b": 22,
"d": 33,
}
fmt.Println(maputil.Minus(m1, m2)) //map[string]int{"c": 3}
}
```
### <span id="Values">Values</span>
<p>Returns a slice of the map's values.</p>
<b>Signature:</b>
```go
func Values[K comparable, V any](m map[K]V) []V
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
}
values := maputil.Values(m)
sort.Strings(values)
fmt.Println(values) // []string{"a", "a", "b", "c", "d"}
}
```

304
docs/maputil_zh-CN.md Normal file
View File

@@ -0,0 +1,304 @@
# Maputil
maputil包包括一些操作map的函数。
<div STYLE="page-break-after: always;"></div>
## 源码:
- [https://github.com/duke-git/lancet/blob/main/maputil/maputil.go](https://github.com/duke-git/lancet/blob/main/maputil/maputil.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/maputil"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录:
- [ForEach](#ForEach)
- [Filter](#Filter)
- [Intersect](#Intersect)
- [Keys](#Keys)
- [Merge](#Merge)
- [Minus](#Minus)
- [Values](#Values)
<div STYLE="page-break-after: always;"></div>
## API文档:
### <span id="ForEach">ForEach</span>
<p>对map中的每对key和value执行iteratee函数</p>
<b>函数签名:</b>
```go
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V))
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
}
var sum int
maputil.ForEach(m, func(_ string, value int) {
sum += value
})
fmt.Println(sum) // 10
}
```
### <span id="Filter">Filter</span>
<p>迭代map中的每对key和value, 返回符合predicate函数的key, value</p>
<b>函数签名:</b>
```go
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
isEven := func(_ string, value int) bool {
return value%2 == 0
}
maputil.Filter(m, func(_ string, value int) {
sum += value
})
res := maputil.Filter(m, isEven)
fmt.Println(res) // map[string]int{"b": 2, "d": 4,}
}
```
### <span id="Intersect">Intersect</span>
<p>多个map的交集操作</p>
<b>函数签名:</b>
```go
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[string]int{
"a": 1,
"b": 2,
"c": 6,
"d": 7,
}
m3 := map[string]int{
"a": 1,
"b": 9,
"e": 9,
}
fmt.Println(maputil.Intersect(m1)) // map[string]int{"a": 1, "b": 2, "c": 3}
fmt.Println(maputil.Intersect(m1, m2)) // map[string]int{"a": 1, "b": 2}
fmt.Println(maputil.Intersect(m1, m2, m3)) // map[string]int{"a": 1}
}
```
### <span id="Keys">Keys</span>
<p>返回map中所有key的切片</p>
<b>函数签名:</b>
```go
func Keys[K comparable, V any](m map[K]V) []K
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
}
keys := maputil.Keys(m)
sort.Ints(keys)
fmt.Println(keys) // []int{1, 2, 3, 4, 5}
}
```
### <span id="Merge">Merge</span>
<p>合并多个maps, 相同的key会被后来的key覆盖</p>
<b>函数签名:</b>
```go
func Merge[K comparable, V any](maps ...map[K]V) map[K]V
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m1 := map[int]string{
1: "a",
2: "b",
}
m2 := map[int]string{
1: "1",
3: "2",
}
fmt.Println(maputil.Merge(m1, m2)) // map[int]string{1:"1", 2:"b", 3:"2",}
}
```
### <span id="Minus">Minus</span>
<p>返回一个map其中的key存在于mapA不存在于mapB.</p>
<b>函数签名:</b>
```go
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[string]int{
"a": 11,
"b": 22,
"d": 33,
}
fmt.Println(maputil.Minus(m1, m2)) //map[string]int{"c": 3}
}
```
### <span id="Values">Values</span>
<p>返回map中所有value的切片</p>
<b>函数签名:</b>
```go
func Values[K comparable, V any](m map[K]V) []V
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
}
values := maputil.Values(m)
sort.Strings(values)
fmt.Println(values) // []string{"a", "a", "b", "c", "d"}
}
```

View File

@@ -5,7 +5,7 @@ Package mathutil implements some functions for math calculation.
## Source:
[https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go)
- [https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,16 +13,20 @@ Package mathutil implements some functions for math calculation.
## Example:
```go
import (
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
```
<div STYLE="page-break-after: always;"></div>
## Index
- [Average](#Average)
- [Exponent](#Exponent)
- [Fibonacci](#Fibonacci)
- [Factorial](#Factorial)
- [Max](#Max)
- [Min](#Min)
- [Percent](#Percent)
- [RoundToFloat](#RoundToFloat)
- [RoundToString](#RoundToString)
@@ -33,6 +37,35 @@ import (
## Documentation
### <span id="Average">Average</span>
<p>Return average value of numbers. Maybe call RoundToFloat to round result.</p>
<b>Signature:</b>
```go
func Average[T lancetconstraints.Number](numbers ...T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
fmt.Println(mathutil.Average(0, 0)) //0
fmt.Println(mathutil.Average(1, 1)) //1
avg := mathutil.Average(1.2, 1.4) //1.2999999998
roundAvg := mmathutil.RoundToFloat(avg, 1) // 1.3
}
```
### <span id="Exponent">Exponent</span>
<p>Calculate x to the nth power.</p>
@@ -48,7 +81,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
@@ -75,7 +108,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
@@ -104,7 +137,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
@@ -117,6 +150,60 @@ func main() {
### <span id="Max">Max</span>
<p>Return max value of numbers.</p>
<b>Signature:</b>
```go
func Max[T lancetconstraints.Number](numbers ...T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
fmt.Println(mathutil.Max(0, 0)) //0
fmt.Println(mathutil.Max(1, 2, 3)) //3
fmt.Println(mathutil.Max(1.2, 1.4, 1.1, 1.4)) //1.4
}
```
### <span id="Min">Min</span>
<p>Return min value of numbers.</p>
<b>Signature:</b>
```go
func Min[T lancetconstraints.Number](numbers ...T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
fmt.Println(mathutil.Min(0, 0)) //0
fmt.Println(mathutil.Min(1, 2, 3)) //1
fmt.Println(mathutil.Min(1.2, 1.4, 1.1, 1.4)) //1.1
}
```
### <span id="Percent">Percent</span>
<p>calculate the percentage of val to total, retain n decimal places.</p>
@@ -132,7 +219,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
@@ -158,7 +245,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
@@ -188,7 +275,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
@@ -217,7 +304,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {

View File

@@ -5,7 +5,7 @@ mathutil包实现了一些数学计算的函数.
## 源码:
[https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go)
- [https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,17 +13,20 @@ mathutil包实现了一些数学计算的函数.
## 用法:
```go
import (
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [Average](#Average)
- [Exponent](#Exponent)
- [Fibonacci](#Fibonacci)
- [Factorial](#Factorial)
- [Max](#Max)
- [Min](#Min)
- [Percent](#Percent)
- [RoundToFloat](#RoundToFloat)
- [RoundToString](#RoundToString)
@@ -34,6 +37,33 @@ import (
## Documentation
### <span id="Average">Average</span>
<p>计算平均数. 可能需要对结果调用RoundToFloat方法四舍五入</p>
<b>函数签名:</b>
```go
func Average[T lancetconstraints.Number](numbers ...T) T
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
fmt.Println(mathutil.Average(0, 0)) //0
fmt.Println(mathutil.Average(1, 1)) //1
avg := mathutil.Average(1.2, 1.4) //1.2999999998
roundAvg := mmathutil.RoundToFloat(avg, 1) // 1.3
}
```
### <span id="Exponent">Exponent</span>
<p>指数计算x的n次方</p>
@@ -49,7 +79,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
@@ -76,7 +106,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
@@ -105,7 +135,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
@@ -117,6 +147,59 @@ func main() {
```
### <span id="Max">Max</span>
<p>返回参数中的最大数</p>
<b>函数签名:</b>
```go
func Max[T lancetconstraints.Number](numbers ...T) T
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
fmt.Println(mathutil.Max(0, 0)) //0
fmt.Println(mathutil.Max(1, 2, 3)) //3
fmt.Println(mathutil.Max(1.2, 1.4, 1.1, 1.4)) //1.4
}
```
### <span id="Min">Min</span>
<p>返回参数中的最小数</p>
<b>函数签名:</b>
```go
func Min[T lancetconstraints.Number](numbers ...T) T
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
fmt.Println(mathutil.Min(0, 0)) //0
fmt.Println(mathutil.Min(1, 2, 3)) //1
fmt.Println(mathutil.Min(1.2, 1.4, 1.1, 1.4)) //1.1
}
```
### <span id="Percent">Percent</span>
<p>计算百分比保留n位小数</p>
@@ -133,7 +216,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
@@ -159,7 +242,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
@@ -189,7 +272,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
@@ -218,7 +301,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {

View File

@@ -5,16 +5,16 @@ Package netutil contains functions to get net information and send http request.
## Source:
[https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
- [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
[https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
- [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
```
@@ -46,7 +46,7 @@ import (
<b>Signature:</b>
```go
func ConvertMapToQueryString(param map[string]interface{}) string
func ConvertMapToQueryString(param map[string]any) string
```
<b>Example:</b>
@@ -55,11 +55,11 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
var m = map[string]interface{}{
var m = map[string]any{
"c": 3,
"a": 1,
"b": 2,
@@ -88,7 +88,7 @@ package main
import (
"fmt"
"net"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -117,7 +117,7 @@ package main
import (
"fmt"
"net"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -144,7 +144,7 @@ package main
import (
"fmt"
"net"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -184,7 +184,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -215,7 +215,7 @@ package main
import (
"fmt"
"net"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -237,10 +237,10 @@ 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]interface{},
// params[1] is query param which type should be url.Values or map[string]any,
// 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 ...interface{}) (*http.Response, error)
func HttpGet(url string, params ...any) (*http.Response, error)
```
<b>Example:</b>
@@ -251,7 +251,7 @@ import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -279,10 +279,10 @@ 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]interface{},
// params[1] is query param which type should be url.Values or map[string]any,
// 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 ...interface{}) (*http.Response, error)
func HttpPost(url string, params ...any) (*http.Response, error)
```
<b>Example:</b>
@@ -294,7 +294,7 @@ import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -328,10 +328,10 @@ 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]interface{},
// params[1] is query param which type should be url.Values or map[string]any,
// 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 ...interface{}) (*http.Response, error)
func HttpPut(url string, params ...any) (*http.Response, error)
```
<b>Example:</b>
@@ -343,7 +343,7 @@ import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -378,10 +378,10 @@ 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]interface{},
// params[1] is query param which type should be url.Values or map[string]any,
// 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 ...interface{}) (*http.Response, error)
func HttpDelete(url string, params ...any) (*http.Response, error)
```
<b>Example:</b>
@@ -393,7 +393,7 @@ import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -417,10 +417,10 @@ 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]interface{},
// params[1] is query param which type should be url.Values or map[string]any,
// 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 ...interface{}) (*http.Response, error)
func HttpPatch(url string, params ...any) (*http.Response, error)
```
<b>Example:</b>
@@ -432,7 +432,7 @@ import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -466,7 +466,7 @@ func main() {
<b>Signature:</b>
```go
func ParseHttpResponse(resp *http.Response, obj interface{}) error
func ParseHttpResponse(resp *http.Response, obj any) error
```
<b>Example:</b>
@@ -478,7 +478,7 @@ import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {

View File

@@ -5,16 +5,15 @@ netutil网络包支持获取ip地址发送http请求。
## 源码:
[https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
[https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
- [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
- [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
```
@@ -46,7 +45,7 @@ import (
<b>函数签名:</b>
```go
func ConvertMapToQueryString(param map[string]interface{}) string
func ConvertMapToQueryString(param map[string]any) string
```
<b>例子:</b>
@@ -55,11 +54,11 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
var m = map[string]interface{}{
var m = map[string]any{
"c": 3,
"a": 1,
"b": 2,
@@ -88,7 +87,7 @@ package main
import (
"fmt"
"net"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -116,7 +115,7 @@ package main
import (
"fmt"
"net"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -143,7 +142,7 @@ package main
import (
"fmt"
"net"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -183,7 +182,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -214,7 +213,7 @@ package main
import (
"fmt"
"net"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -236,10 +235,10 @@ func main() {
```go
// params[0] http请求header类型必须是http.Header或者map[string]string
// params[1] http查询字符串类型必须是url.Values或者map[string]interface{}
// params[1] http查询字符串类型必须是url.Values或者map[string]any
// params[2] post请求体类型必须是[]byte
// params[3] http client类型必须是http.Client
func HttpGet(url string, params ...interface{}) (*http.Response, error)
func HttpGet(url string, params ...any) (*http.Response, error)
```
<b>例子:</b>
@@ -250,7 +249,7 @@ import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -278,10 +277,10 @@ func main() {
```go
// params[0] http请求header类型必须是http.Header或者map[string]string
// params[1] http查询字符串类型必须是url.Values或者map[string]interface{}
// params[1] http查询字符串类型必须是url.Values或者map[string]any
// params[2] post请求体类型必须是[]byte
// params[3] http client类型必须是http.Client
func HttpPost(url string, params ...interface{}) (*http.Response, error)
func HttpPost(url string, params ...any) (*http.Response, error)
```
<b>例子:</b>
@@ -293,7 +292,7 @@ import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -327,10 +326,10 @@ func main() {
```go
// params[0] http请求header类型必须是http.Header或者map[string]string
// params[1] http查询字符串类型必须是url.Values或者map[string]interface{}
// params[1] http查询字符串类型必须是url.Values或者map[string]any
// params[2] post请求体类型必须是[]byte
// params[3] http client类型必须是http.Client
func HttpPut(url string, params ...interface{}) (*http.Response, error)
func HttpPut(url string, params ...any) (*http.Response, error)
```
<b>Example:</b>
@@ -342,7 +341,7 @@ import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -377,10 +376,10 @@ func main() {
```go
// params[0] http请求header类型必须是http.Header或者map[string]string
// params[1] http查询字符串类型必须是url.Values或者map[string]interface{}
// params[1] http查询字符串类型必须是url.Values或者map[string]any
// params[2] post请求体类型必须是[]byte
// params[3] http client类型必须是http.Client
func HttpDelete(url string, params ...interface{}) (*http.Response, error)
func HttpDelete(url string, params ...any) (*http.Response, error)
```
<b>例子:</b>
@@ -392,7 +391,7 @@ import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -416,10 +415,10 @@ func main() {
```go
// params[0] http请求header类型必须是http.Header或者map[string]string
// params[1] http查询字符串类型必须是url.Values或者map[string]interface{}
// params[1] http查询字符串类型必须是url.Values或者map[string]any
// params[2] post请求体类型必须是[]byte
// params[3] http client类型必须是http.Client
func HttpPatch(url string, params ...interface{}) (*http.Response, error)
func HttpPatch(url string, params ...any) (*http.Response, error)
```
<b>例子:</b>
@@ -431,7 +430,7 @@ import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
@@ -465,7 +464,7 @@ func main() {
<b>函数签名:</b>
```go
func ParseHttpResponse(resp *http.Response, obj interface{}) error
func ParseHttpResponse(resp *http.Response, obj any) error
```
<b>例子:</b>
@@ -477,7 +476,7 @@ import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/netutil"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {

View File

@@ -5,7 +5,7 @@ Package random implements some basic functions to generate random int and string
## Source:
[https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
- [https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ Package random implements some basic functions to generate random int and string
## Usage:
```go
import (
"github.com/duke-git/lancet/random"
"github.com/duke-git/lancet/v2/random"
)
```
@@ -45,7 +45,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/random"
"github.com/duke-git/lancet/v2/random"
)
func main() {
@@ -70,7 +70,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/random"
"github.com/duke-git/lancet/v2/random"
)
func main() {
@@ -96,7 +96,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/random"
"github.com/duke-git/lancet/v2/random"
)
func main() {
@@ -123,7 +123,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/random"
"github.com/duke-git/lancet/v2/random"
)
func main() {

View File

@@ -5,7 +5,7 @@ random随机数生成器包可以生成随机[]bytes, int, string。
## 源码:
[https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
- [https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ random随机数生成器包可以生成随机[]bytes, int, string。
## 用法:
```go
import (
"github.com/duke-git/lancet/random"
"github.com/duke-git/lancet/v2/random"
)
```
@@ -46,7 +46,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/random"
"github.com/duke-git/lancet/v2/random"
)
func main() {
@@ -71,7 +71,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/random"
"github.com/duke-git/lancet/v2/random"
)
func main() {
@@ -97,7 +97,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/random"
"github.com/duke-git/lancet/v2/random"
)
func main() {
@@ -123,7 +123,7 @@ package main
import (
"fmt"
"github.com/duke-git/lancet/random"
"github.com/duke-git/lancet/v2/random"
)
func main() {

View File

@@ -5,7 +5,7 @@ Package retry is for executing a function repeatedly until it was successful or
## Source:
[https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
- [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ Package retry is for executing a function repeatedly until it was successful or
## Usage:
```go
import (
"github.com/duke-git/lancet/retry"
"github.com/duke-git/lancet/v2/retry"
)
```
@@ -46,7 +46,7 @@ import (
"context"
"errors"
"fmt"
"github.com/duke-git/lancet/retry"
"github.com/duke-git/lancet/v2/retry"
"time"
)
@@ -92,7 +92,7 @@ import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/retry"
"github.com/duke-git/lancet/v2/retry"
)
func main() {
@@ -134,7 +134,7 @@ import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/retry"
"github.com/duke-git/lancet/v2/retry"
)
func main() {
@@ -173,7 +173,7 @@ import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/retry"
"github.com/duke-git/lancet/v2/retry"
)
func main() {
@@ -213,7 +213,7 @@ import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/retry"
"github.com/duke-git/lancet/v2/retry"
)
func main() {

View File

@@ -5,7 +5,7 @@ retry重试执行函数直到函数运行成功或被context cancel。
## 源码:
[https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
- [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ retry重试执行函数直到函数运行成功或被context cancel。
## 用法:
```go
import (
"github.com/duke-git/lancet/retry"
"github.com/duke-git/lancet/v2/retry"
)
```
@@ -94,7 +94,7 @@ import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/retry"
"github.com/duke-git/lancet/v2/retry"
)
func main() {
@@ -136,7 +136,7 @@ import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/retry"
"github.com/duke-git/lancet/v2/retry"
)
func main() {
@@ -175,7 +175,7 @@ import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/retry"
"github.com/duke-git/lancet/v2/retry"
)
func main() {
@@ -215,7 +215,7 @@ import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/retry"
"github.com/duke-git/lancet/v2/retry"
)
func main() {

View File

@@ -5,7 +5,7 @@ Package slice implements some functions to manipulate slice.
## Source:
[https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go)
- [https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ Package slice implements some functions to manipulate slice.
## Usage:
```go
import (
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
```
@@ -28,7 +28,8 @@ import (
- [Count](#Count)
- [Difference](#Difference)
- [DifferenceBy](#DifferenceBy)
- [DeleteByIndex](#DeleteByIndex)
- [DifferenceWith](#DifferenceWith)
- [DeleteAt](#DeleteAt)
- [Drop](#Drop)
- [Every](#Every)
- [Filter](#Filter)
@@ -36,45 +37,44 @@ import (
- [FindLast](#FindLast)
- [FlattenDeep](#FlattenDeep)
- [ForEach](#ForEach)
- [GroupBy](#GroupBy)
- [GroupWith](#GroupWith)
- [IntSlice](#IntSlice)
- [InterfaceSlice](#InterfaceSlice)
- [Intersection](#Intersection)
- [InsertByIndex](#InsertByIndex)
- [InsertAt](#InsertAt)
- [Map](#Map)
- [ReverseSlice](#ReverseSlice)
- [Reverse](#Reverse)
- [Reduce](#Reduce)
- [Shuffle](#Shuffle)
- [SortByField](#SortByField)
- [Some](#Some)
- [StringSlice](#StringSlice)
- [SymmetricDifference](#SymmetricDifference)
- [Unique](#Unique)
- [Union](#Union)
- [UpdateByIndex](#UpdateByIndex)
- [UpdateAt](#UpdateAt)
- [Without](#Without)
<div STYLE="page-break-after: always;"></div>
## Documentation
## Note:
1. param which type is interface{} in below functions should be slice.
### <span id="Contain">Contain</span>
<p>Check if the value is in the slice or not. iterableType param can be string, map or slice.</p>
<p>Check if the value is in the slice or not.</p>
<b>Signature:</b>
```go
func Contain(iterableType interface{}, value interface{}) bool
func Contain[T any](slice []T, value T) bool
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -90,14 +90,14 @@ func main() {
<b>Signature:</b>
```go
func ContainSubSlice(slice interface{}, subslice interface{}) bool
func ContainSubSlice[T any](slice, subslice []T) bool
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -115,20 +115,20 @@ func main() {
<b>Signature:</b>
```go
func Chunk(slice []interface{}, size int) [][]interface{}
func Chunk[T any](slice []T, size int) [][]T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
arr := []string{"a", "b", "c", "d", "e"}
res := slice.Chunk(InterfaceSlice(arr), 3)
fmt.Println(res) //[][]interface{}{{"a", "b", "c"}, {"d", "e"}}
fmt.Println(res) //[][]any{{"a", "b", "c"}, {"d", "e"}}
}
```
@@ -140,14 +140,14 @@ func main() {
<b>Signature:</b>
```go
func Compact(slice interface{}) interface{}
func Compact[T any](slice []T) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -163,14 +163,14 @@ func main() {
<b>Signature:</b>
```go
func Concat(slice interface{}, values ...interface{}) interface{}
func Concat[T any](slice []T, values ...[]T) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -185,19 +185,19 @@ func main() {
### <span id="Count">Count</span>
<p>Count iterates over elements of slice, returns a count of all matched elements. The function signature should be func(index int, value interface{}) bool.</p>
<p>Count iterates over elements of slice, returns a count of all matched elements.</p>
<b>Signature:</b>
```go
func Count(slice, function interface{}) int
func Count[T any](slice []T, predicate func(index int, t T) bool) int
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -220,14 +220,14 @@ func main() {
<b>Signature:</b>
```go
func Difference(slice1, slice2 interface{}) interface{}
func Difference[T comparable](slice, comparedSlice []T) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -248,14 +248,14 @@ func main() {
<b>Signature:</b>
```go
func DifferenceBy(slice interface{}, comparedSlice interface{}, iterateeFn interface{}) interface{}
func DifferenceBy[T any](slice []T, comparedSlice []T, iteratee func(index int, t T) T) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -271,29 +271,55 @@ func main() {
```
### <span id="DeleteByIndex">DeleteByIndex</span>
<p>Delete the element of slice from start index to end index - 1.</p>
### <span id="DifferenceWith">DifferenceWith</span>
<p>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.</p>
<b>Signature:</b>
```go
func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error)
func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value, otherValue T) bool) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
res1 := slice.DeleteByIndex([]string{"a", "b", "c", "d", "e"}, 3)
s1 := []int{1, 2, 3, 4, 5}
s2 := []int{4, 5, 6, 7, 8}
isDouble := func(v1, v2 int) bool {
return v2 == 2*v1
}
res := slice.DifferenceWith(s1, s2, isDouble)
fmt.Println(res) //[]int{1, 5}
}
```
### <span id="DeleteAt">DeleteAt</span>
<p>Delete the element of slice from start index to end index - 1.</p>
<b>Signature:</b>
```go
func DeleteAt[T any](slice []T, start int, end ...int)
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
res1 := slice.DeleteAt([]string{"a", "b", "c", "d", "e"}, 3)
fmt.Println(res1) //[]string{"a", "b", "c", "e"}
res2 := slice.DeleteByIndex([]string{"a", "b", "c", "d", "e"}, 0, 2)
res2 := slice.DeleteAt([]string{"a", "b", "c", "d", "e"}, 0, 2)
fmt.Println(res2) //[]string{"c", "d", "e"}
}
@@ -308,14 +334,14 @@ func main() {
<b>Signature:</b>
```go
func Drop(slice interface{}, n int) interface{}
func Drop[T any](slice []T, n int) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -334,19 +360,19 @@ func main() {
### <span id="Every">Every</span>
<p>Return true if all of the values in the slice pass the predicate function. The function signature should be func(index int, value interface{}) bool.</p>
<p>Return true if all of the values in the slice pass the predicate function.</p>
<b>Signature:</b>
```go
func Every(slice, function interface{}) bool
func Every[T any](slice []T, predicate func(index int, t T) bool) bool
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -364,19 +390,19 @@ func main() {
### <span id="Filter">Filter</span>
<p>Return all elements which match the function. Function signature should be func(index int, value interface{}) bool.</p>
<p>Return all elements which match the function.</p>
<b>Signature:</b>
```go
func Filter(slice, function interface{}) interface{}
func Filter[T any](slice []T, predicate func(index int, t T) bool) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -393,19 +419,19 @@ func main() {
### <span id="Find">Find</span>
<p>Iterates over elements of slice, returning the first one that passes a truth test on function.function signature should be func(index int, value interface{}) bool.</p>
<p>Iterates over elements of slice, returning the first one that passes a truth test on function.</p>
<b>Signature:</b>
```go
func Find(slice, function interface{}) (interface{}, bool)
func Find[T any](slice []T, predicate func(index int, t T) bool) (*T, bool)
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -424,19 +450,19 @@ func main() {
### <span id="FindLast">FindLast</span>
<p>iterates over elements of slice from end to begin, returning the last one that passes a truth test on function. The function signature should be func(index int, value interface{}) bool.</p>
<p>iterates over elements of slice from end to begin, returning the last one that passes a truth test on function.</p>
<b>Signature:</b>
```go
func FindLast(slice, function interface{}) (interface{}, bool)
func FindLast[T any](slice []T, predicate func(index int, t T) bool) (*T, bool)
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -459,14 +485,14 @@ func main() {
<b>Signature:</b>
```go
func FlattenDeep(slice interface{}) interface{}
func FlattenDeep(slice any) any
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -481,19 +507,19 @@ func main() {
### <span id="ForEach">ForEach</span>
<p>Iterates over elements of slice and invokes function for each element, function signature should be func(index int, value interface{}).</p>
<p>Iterates over elements of slice and invokes function for each element.</p>
<b>Signature:</b>
```go
func ForEach(slice, function interface{})
func ForEach[T any](slice []T, iteratee func(index int, t T))
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -510,19 +536,19 @@ func main() {
### <span id="GroupBy">GroupBy</span>
<p>Iterates over elements of the slice, each element will be group by criteria, returns two slices. The function signature should be func(index int, value interface{}) bool.</p>
<p>Iterates over elements of the slice, each element will be group by criteria, returns two slices.</p>
<b>Signature:</b>
```go
func GroupBy(slice, function interface{}) (interface{}, interface{})
func GroupBy[T any](slice []T, groupFn func(index int, t T) bool) ([]T, []T)
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -540,24 +566,52 @@ func main() {
### <span id="IntSlice">IntSlice</span>
<p>Convert interface slice to int slice.</p>
### <span id="GroupWith">GroupWith</span>
<p>Return a map composed of keys generated from the results of running each element of slice thru iteratee.</p>
<b>Signature:</b>
```go
func IntSlice(slice interface{}) []int
func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
var nums = []interface{}{1, 2, 3}
nums := []float64{6.1, 4.2, 6.3}
floor := func(num float64) float64 {
return math.Floor(num)
}
res := slice.GroupWith(nums, floor)
fmt.Println(res) //map[float64][]float64{ 4: {4.2}, 6: {6.1, 6.3},}
}
```
### <span id="IntSlice">IntSlice</span>
<p>Convert interface slice to int slice.</p>
<b>Signature:</b>
```go
func IntSlice(slice any) []int
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
var nums = []any{1, 2, 3}
res := slice.IntSlice(nums)
fmt.Println(res) //[]int{1, 2, 3}
}
@@ -572,20 +626,20 @@ func main() {
<b>Signature:</b>
```go
func InterfaceSlice(slice interface{}) []interface{}
func InterfaceSlice(slice any) []any
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
var nums = []int{}{1, 2, 3}
res := slice.InterfaceSlice(nums)
fmt.Println(res) //[]interface{}{1, 2, 3}
fmt.Println(res) //[]any{1, 2, 3}
}
```
@@ -598,14 +652,14 @@ func main() {
<b>Signature:</b>
```go
func Intersection(slices ...interface{}) interface{}
func Intersection[T any](slices ...[]T) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -620,29 +674,29 @@ func main() {
### <span id="InsertByIndex">InsertByIndex</span>
### <span id="InsertAt">InsertAt</span>
<p>insert the element into slice at index.</p>
<b>Signature:</b>
```go
func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error)
func InsertAt[T any](slice []T, index int, value any) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
s := []string{"a", "b", "c"}
res1, _ := slice.InsertByIndex(s, 0, "1")
res1, _ := slice.InsertAt(s, 0, "1")
fmt.Println(res1) //[]string{"1", "a", "b", "c"}
res2, _ := slice.InsertByIndex(s, 3, []string{"1", "2", "3"})
res2, _ := slice.InsertAt(s, 3, []string{"1", "2", "3"})
fmt.Println(res2) //[]string{"a", "b", "c", "1", "2", "3"}
}
```
@@ -651,19 +705,19 @@ func main() {
### <span id="Map">Map</span>
<p>Creates an slice of values by running each element in slice thru function, function signature should be func(index int, value interface{}) interface{}.</p>
<p>Creates an slice of values by running each element in slice thru function.</p>
<b>Signature:</b>
```go
func Map(slice, function interface{}) interface{}
func Map[T any, U any](slice []T, iteratee func(index int, t T) U) []U
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -679,25 +733,25 @@ func main() {
### <span id="ReverseSlice">ReverseSlice</span>
### <span id="Reverse">Reverse</span>
<p>Reverse the elements order in slice.</p>
<b>Signature:</b>
```go
func ReverseSlice(slice interface{})
func Reverse[T any](slice []T)
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
nums := []int{1, 2, 3, 4}
slice.ReverseSlice(nums)
slice.Reverse(nums)
fmt.Println(res) //[]int{4, 3, 2, 1}
}
```
@@ -705,19 +759,19 @@ func main() {
### <span id="Reduce">Reduce</span>
<p>Reduce slice, function signature should be func(index int, value1, value2 interface{}) interface{}.</p>
<p>Reduce slice.</p>
<b>Signature:</b>
```go
func Reduce(slice, function, zero interface{}) interface{}
func Reduce[T any](slice []T, iteratee func(index int, t1, t2 T) T, initial T) T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -739,14 +793,14 @@ func main() {
<b>Signature:</b>
```go
func Shuffle(slice interface{}) interface{}
func Shuffle[T any](slice []T) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -764,14 +818,14 @@ func main() {
<b>Signature:</b>
```go
func SortByField(slice interface{}, field string, sortType ...string) error
func SortByField(slice any, field string, sortType ...string) error
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -802,19 +856,19 @@ func main() {
### <span id="Some">Some</span>
<p>Return true if any of the values in the list pass the predicate function, function signature should be func(index int, value interface{}) bool.</p>
<p>Return true if any of the values in the list pass the predicate function.</p>
<b>Signature:</b>
```go
func Some(slice, function interface{}) bool
func Some[T any](slice []T, predicate func(index int, t T) bool) bool
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -836,18 +890,18 @@ func main() {
<b>Signature:</b>
```go
func StringSlice(slice interface{}) []string
func StringSlice(slice any) []string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
var s = []interface{}{"a", "b", "c"}
var s = []any{"a", "b", "c"}
res := slice.StringSlice(s)
fmt.Println(res) //[]string{"a", "b", "c"}
}
@@ -856,20 +910,49 @@ func main() {
### <span id="SymmetricDifference">SymmetricDifference</span>
<p>Create a slice whose element is in given slices, but not in both slices.</p>
<b>Signature:</b>
```go
func SymmetricDifference[T any](slices ...[]T) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
s1 := []int{1, 2, 3}
s2 := []int{1, 2, 4}
s3 := []int{1, 2, 3, 5}
fmt.Println(slice.SymmetricDifference(s1)) //[]int{1, 2, 3}
fmt.Println(slice.SymmetricDifference(s1, s2)) //[]int{3, 4}
fmt.Println(slice.SymmetricDifference(s1, s2, s3)) //[]int{3, 4, 5}
}
```
### <span id="Unique">Unique</span>
<p>Remove duplicate elements in slice.</p>
<b>Signature:</b>
```go
func Unique(slice interface{}) interface{}
func Unique[T any](slice []T) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -886,14 +969,14 @@ func main() {
<b>Signature:</b>
```go
func Union(slices ...interface{}) interface{}
func Union[T any](slices ...[]T) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -907,26 +990,26 @@ func main() {
### <span id="UpdateByIndex">UpdateByIndex</span>
### <span id="UpdateAt">UpdateAt</span>
<p>Update the slice element at index. if param index < 0 or index >= len(slice), will return error. </p>
<b>Signature:</b>
```go
func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}, error)
func UpdateAt[T any](slice []T, index int, value T) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
s := []string{"a", "b", "c"}
res1, _ := slice.UpdateByIndex(s, 0, "1")
res1, _ := slice.UpdateAt(s, 0, "1")
fmt.Println(res1) //[]string{"1", "b", "c"}
}
```
@@ -940,14 +1023,14 @@ func main() {
<b>Signature:</b>
```go
func Without(slice interface{}, values ...interface{}) interface{}
func Without[T any](slice []T, values ...T) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {

View File

@@ -5,7 +5,7 @@ slice包包含操作切片的方法集合。
## 源码:
[https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go)
- [https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ slice包包含操作切片的方法集合。
## 用法:
```go
import (
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
```
@@ -28,7 +28,8 @@ import (
- [Count](#Count)
- [Difference](#Difference)
- [DifferenceBy](#DifferenceBy)
- [DeleteByIndex](#DeleteByIndex)
- [DifferenceWith](#DifferenceWith)
- [DeleteAt](#DeleteAt)
- [Drop](#Drop)
- [Every](#Every)
- [Filter](#Filter)
@@ -38,20 +39,22 @@ import (
- [ForEach](#ForEach)
- [GroupBy](#GroupBy)
- [GroupWith](#GroupWith)
- [IntSlice](#IntSlice)
- [InterfaceSlice](#InterfaceSlice)
- [Intersection](#Intersection)
- [InsertByIndex](#InsertByIndex)
- [InsertAt](#InsertAt)
- [Map](#Map)
- [ReverseSlice](#ReverseSlice)
- [Reverse](#Reverse)
- [Reduce](#Reduce)
- [Shuffle](#Shuffle)
- [SortByField](#SortByField)
- [Some](#Some)
- [StringSlice](#StringSlice)
- [SymmetricDifference](#SymmetricDifference)
- [Unique](#Unique)
- [Union](#Union)
- [UpdateByIndex](#UpdateByIndex)
- [UpdateAt](#UpdateAt)
- [Without](#Without)
<div STYLE="page-break-after: always;"></div>
@@ -64,14 +67,14 @@ import (
<b>函数签名:</b>
```go
func Contain(iterableType interface{}, value interface{}) bool
func Contain[T any](slice []T, value T) bool
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -87,14 +90,14 @@ func main() {
<b>函数签名:</b>
```go
func ContainSubSlice(slice interface{}, subslice interface{}) bool
func ContainSubSlice[T any](slice, subslice []T) bool
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -112,20 +115,20 @@ func main() {
<b>函数签名:</b>
```go
func Chunk(slice []interface{}, size int) [][]interface{}
func Chunk[T any](slice []T, size int) [][]T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
arr := []string{"a", "b", "c", "d", "e"}
res := slice.Chunk(InterfaceSlice(arr), 3)
fmt.Println(res) //[][]interface{}{{"a", "b", "c"}, {"d", "e"}}
fmt.Println(res) //[][]any{{"a", "b", "c"}, {"d", "e"}}
}
```
@@ -137,14 +140,14 @@ func main() {
<b>函数签名:</b>
```go
func Compact(slice interface{}) interface{}
func Compact[T any](slice []T) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -160,14 +163,14 @@ func main() {
<b>函数签名:</b>
```go
func Concat(slice interface{}, values ...interface{}) interface{}
func Concat[T any](slice []T, values ...[]T) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -182,19 +185,19 @@ func main() {
### <span id="Count">Count</span>
<p>遍历切片对每个元素执行函数function. 返回符合函数返回值为true的元素的个数函数签名必须是func(index int, value interface{}) bool</p>
<p>遍历切片对每个元素执行函数function. 返回符合函数返回值为true的元素的个数</p>
<b>函数签名:</b>
```go
func Count(slice, function interface{}) int
func Count[T any](slice []T, predicate func(index int, t T) bool) int
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -217,14 +220,14 @@ func main() {
<b>函数签名:</b>
```go
func Difference(slice1, slice2 interface{}) interface{}
func Difference[T comparable](slice, comparedSlice []T) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -245,14 +248,14 @@ func main() {
<b>函数签名:</b>
```go
func DifferenceBy(slice interface{}, comparedSlice interface{}, iterateeFn interface{}) interface{}
func DifferenceBy[T any](slice []T, comparedSlice []T, iteratee func(index int, t T) T) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -269,28 +272,56 @@ func main() {
### <span id="DeleteByIndex">DeleteByIndex</span>
<p>删除切片中从开始索引到结束索引-1的元素</p>
### <span id="DifferenceWith">DifferenceWith</span>
<p>DifferenceWith 接受比较器,该比较器被调用以将切片的元素与值进行比较。 结果值的顺序和引用由第一个切片确定</p>
<b>函数签名:</b>
```go
func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error)
func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value, otherValue T) bool) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
res1 := slice.DeleteByIndex([]string{"a", "b", "c", "d", "e"}, 3)
s1 := []int{1, 2, 3, 4, 5}
s2 := []int{4, 5, 6, 7, 8}
isDouble := func(v1, v2 int) bool {
return v2 == 2*v1
}
res := slice.DifferenceWith(s1, s2, isDouble)
fmt.Println(res) //[]int{1, 5}
}
```
### <span id="DeleteAt">DeleteAt</span>
<p>删除切片中从开始索引到结束索引-1的元素</p>
<b>函数签名:</b>
```go
func DeleteAt[T any](slice []T, start int, end ...int)
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
res1 := slice.DeleteAt([]string{"a", "b", "c", "d", "e"}, 3)
fmt.Println(res1) //[]string{"a", "b", "c", "e"}
res2 := slice.DeleteByIndex([]string{"a", "b", "c", "d", "e"}, 0, 2)
res2 := slice.DeleteAt([]string{"a", "b", "c", "d", "e"}, 0, 2)
fmt.Println(res2) //[]string{"c", "d", "e"}
}
@@ -305,14 +336,14 @@ func main() {
<b>函数签名:</b>
```go
func Drop(slice interface{}, n int) interface{}
func Drop[T any](slice []T, n int) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -331,19 +362,19 @@ func main() {
### <span id="Every">Every</span>
<p>如果切片中的所有值都通过谓词函数则返回true。 函数签名应该是func(index int, value interface{}) bool</p>
<p>如果切片中的所有值都通过谓词函数则返回true。 函数签名应该是func(index int, value any) bool</p>
<b>函数签名:</b>
```go
func Every(slice, function interface{}) bool
func Every[T any](slice []T, predicate func(index int, t T) bool) bool
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -361,19 +392,19 @@ func main() {
### <span id="Filter">Filter</span>
<p>返回与函数匹配的所有元素。 函数签名应该是 func(index int, value interface{}) bool</p>
<p>返回与函数匹配的所有元素。 函数签名应该是 func(index int, value any) bool</p>
<b>函数签名:</b>
```go
func Filter(slice, function interface{}) interface{}
func Filter[T any](slice []T, predicate func(index int, t T) bool) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -390,19 +421,19 @@ func main() {
### <span id="Find">Find</span>
<p>遍历slice的元素返回第一个通过function真值测试的元素。函数签名应该是 func(index int, value interface{}) bool</p>
<p>遍历slice的元素返回第一个通过function真值测试的元素</p>
<b>函数签名:</b>
```go
func Find(slice, function interface{}) (interface{}, bool)
func Find[T any](slice []T, predicate func(index int, t T) bool) (*T, bool)
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -421,19 +452,19 @@ func main() {
### <span id="FindLast">FindLast</span>
<p>从头到尾遍历 slice 的元素,返回最后一个通过函数真值测试的元素。 函数签名应该是 func(index int, value interface{}) bool。</p>
<p>从头到尾遍历 slice 的元素,返回最后一个通过函数真值测试的元素。</p>
<b>函数签名:</b>
```go
func FindLast(slice, function interface{}) (interface{}, bool)
func FindLast[T any](slice []T, predicate func(index int, t T) bool) (*T, bool)
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -456,14 +487,14 @@ func main() {
<b>函数签名:</b>
```go
func FlattenDeep(slice interface{}) interface{}
func FlattenDeep(slice any) any
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -478,19 +509,19 @@ func main() {
### <span id="ForEach">ForEach</span>
<p>遍历slice的元素并为每个元素调用函数函数签名应该是func(index int, value interface{})</p>
<p>遍历slice的元素并为每个元素调用函数</p>
<b>函数签名:</b>
```go
func ForEach(slice, function interface{})
func ForEach[T any](slice []T, iteratee func(index int, t T))
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -507,19 +538,19 @@ func main() {
### <span id="GroupBy">GroupBy</span>
<p>迭代切片的元素,每个元素将按条件分组,返回两个切片。 函数签名应该是func(index int, value interface{}) bool</p>
<p>迭代切片的元素,每个元素将按条件分组,返回两个切片</p>
<b>函数签名:</b>
```go
func GroupBy(slice, function interface{}) (interface{}, interface{})
func GroupBy[T any](slice []T, groupFn func(index int, t T) bool) ([]T, []T)
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -536,6 +567,32 @@ func main() {
### <span id="GroupWith">GroupWith</span>
<p>创建一个mapkey是iteratee遍历slice中的每个元素返回的结果。 分组值的顺序是由他们出现在slice中的顺序确定的。每个键对应的值负责生成key的元素组成的数组。iteratee调用1个参数 (value)</p>
<b>函数签名:</b>
```go
func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
nums := []float64{6.1, 4.2, 6.3}
floor := func(num float64) float64 {
return math.Floor(num)
}
res := slice.GroupWith(nums, floor)
fmt.Println(res) //map[float64][]float64{ 4: {4.2}, 6: {6.1, 6.3},}
}
```
### <span id="IntSlice">IntSlice</span>
<p>将接口切片转换为int切片</p>
@@ -543,18 +600,18 @@ func main() {
<b>函数签名:</b>
```go
func IntSlice(slice interface{}) []int
func IntSlice(slice any) []int
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
var nums = []interface{}{1, 2, 3}
var nums = []any{1, 2, 3}
res := slice.IntSlice(nums)
fmt.Println(res) //[]int{1, 2, 3}
}
@@ -569,20 +626,20 @@ func main() {
<b>函数签名:</b>
```go
func InterfaceSlice(slice interface{}) []interface{}
func InterfaceSlice(slice any) []any
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
var nums = []int{}{1, 2, 3}
res := slice.InterfaceSlice(nums)
fmt.Println(res) //[]interface{}{1, 2, 3}
fmt.Println(res) //[]any{1, 2, 3}
}
```
@@ -595,14 +652,14 @@ func main() {
<b>函数签名:</b>
```go
func Intersection(slices ...interface{}) interface{}
func Intersection[T any](slices ...[]T) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -617,29 +674,29 @@ func main() {
### <span id="InsertByIndex">InsertByIndex</span>
### <span id="InsertAt">InsertAt</span>
<p>将元素插入到索引处的切片中</p>
<b>函数签名:</b>
```go
func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error)
func InsertAt[T any](slice []T, index int, value any) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
s := []string{"a", "b", "c"}
res1, _ := slice.InsertByIndex(s, 0, "1")
res1, _ := slice.InsertAt(s, 0, "1")
fmt.Println(res1) //[]string{"1", "a", "b", "c"}
res2, _ := slice.InsertByIndex(s, 3, []string{"1", "2", "3"})
res2, _ := slice.InsertAt(s, 3, []string{"1", "2", "3"})
fmt.Println(res2) //[]string{"a", "b", "c", "1", "2", "3"}
}
```
@@ -648,19 +705,19 @@ func main() {
### <span id="Map">Map</span>
<p>通过运行函数slice中的每个元素来创建一个切片函数签名应该是func(index int, value interface{}) interface{}。</p>
<p>通过运行函数slice中的每个元素来创建一个切片</p>
<b>函数签名:</b>
```go
func Map(slice, function interface{}) interface{}
func Map[T any, U any](slice []T, iteratee func(index int, t T) U) []U
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -676,25 +733,25 @@ func main() {
### <span id="ReverseSlice">ReverseSlice</span>
### <span id="Reverse">Reverse</span>
<p>反转切片中的元素顺序</p>
<b>函数签名:</b>
```go
func ReverseSlice(slice interface{})
func Reverse[T any](slice []T)
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
nums := []int{1, 2, 3, 4}
slice.ReverseSlice(nums)
slice.Reverse(nums)
fmt.Println(res) //[]int{4, 3, 2, 1}
}
```
@@ -702,19 +759,19 @@ func main() {
### <span id="Reduce">Reduce</span>
<p>将slice中的元素运行函数返回运行结果。函数签名应该是func(index int, value1, value2 interface{}) interface{}。</p>
<p>将slice中的元素依次运行函数,返回运行结果</p>
<b>函数签名:</b>
```go
func Reduce(slice, function, zero interface{}) interface{}
func Reduce[T any](slice []T, iteratee func(index int, t1, t2 T) T, initial T) T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -736,14 +793,14 @@ func main() {
<b>函数签名:</b>
```go
func Shuffle(slice interface{}) interface{}
func Shuffle[T any](slice []T) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -761,14 +818,14 @@ func main() {
<b>函数签名:</b>
```go
func SortByField(slice interface{}, field string, sortType ...string) error
func SortByField(slice any, field string, sortType ...string) error
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -799,19 +856,19 @@ func main() {
### <span id="Some">Some</span>
<p>如果列表中的任何值通过谓词函数则返回true函数签名应该是func(index int, value interface{}) bool .</p>
<p>如果列表中的任何值通过谓词函数则返回true</p>
<b>函数签名:</b>
```go
func Some(slice, function interface{}) bool
func Some[T any](slice []T, predicate func(index int, t T) bool) bool
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -833,18 +890,18 @@ func main() {
<b>函数签名:</b>
```go
func StringSlice(slice interface{}) []string
func StringSlice(slice any) []string
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
var s = []interface{}{"a", "b", "c"}
var s = []any{"a", "b", "c"}
res := slice.StringSlice(s)
fmt.Println(res) //[]string{"a", "b", "c"}
}
@@ -853,20 +910,48 @@ func main() {
### <span id="Unique">Unique</span>
<p>删除切片中的重复元素</p>
### <span id="SymmetricDifference">SymmetricDifference</span>
<p>返回一个切片,其中的元素存在于参数切片中,但不同时存储在于参数切片中(交集取反)</p>
<b>函数签名:</b>
```go
func Unique(slice interface{}) interface{}
func SymmetricDifference[T any](slices ...[]T) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
s1 := []int{1, 2, 3}
s2 := []int{1, 2, 4}
s3 := []int{1, 2, 3, 5}
fmt.Println(slice.SymmetricDifference(s1)) //[]int{1, 2, 3}
fmt.Println(slice.SymmetricDifference(s1, s2)) //[]int{3, 4}
fmt.Println(slice.SymmetricDifference(s1, s2, s3)) //[]int{3, 4, 5}
}
```
### <span id="Unique">Unique</span>
<p>删除切片中的重复元素</p>
<b>函数签名:</b>
```go
func Unique[T any](slice []T) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -883,14 +968,14 @@ func main() {
<b>函数签名:</b>
```go
func Union(slices ...interface{}) interface{}
func Union[T any](slices ...[]T) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
@@ -904,26 +989,26 @@ func main() {
### <span id="UpdateByIndex">UpdateByIndex</span>
### <span id="UpdateAt">UpdateAt</span>
<p>更新索引处的切片元素。 如果 param index < 0 或 index >= len(slice),将返回错误</p>
<b>函数签名:</b>
```go
func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}, error)
func UpdateAt[T any](slice []T, index int, value T) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
s := []string{"a", "b", "c"}
res1, _ := slice.UpdateByIndex(s, 0, "1")
res1, _ := slice.UpdateAt(s, 0, "1")
fmt.Println(res1) //[]string{"1", "b", "c"}
}
```
@@ -937,14 +1022,14 @@ func main() {
<b>函数签名:</b>
```go
func Without(slice interface{}, values ...interface{}) interface{}
func Without[T any](slice []T, values ...T) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
"github.com/duke-git/lancet/v2/slice"
)
func main() {

View File

@@ -5,7 +5,7 @@ Package strutil contains some functions to manipulate string.
## Source:
[https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go)
- [https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ Package strutil contains some functions to manipulate string.
## Usage:
```go
import (
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
```
@@ -57,7 +57,7 @@ func After(s, char string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -87,7 +87,7 @@ func AfterLast(s, char string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -118,7 +118,7 @@ func Before(s, char string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -149,7 +149,7 @@ func BeforeLast(s, char string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -180,7 +180,7 @@ func CamelCase(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -214,7 +214,7 @@ func Capitalize(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -237,14 +237,14 @@ func main() {
<b>Signature:</b>
```go
func IsString(v interface{}) bool
func IsString(v any) bool
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -272,7 +272,7 @@ func KebabCase(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -306,7 +306,7 @@ func LowerFirst(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -340,7 +340,7 @@ func UpperFirst(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -374,7 +374,7 @@ func PadEnd(source string, size int, padStr string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -408,7 +408,7 @@ func PadStart(source string, size int, padStr string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -442,7 +442,7 @@ func ReverseStr(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -469,7 +469,7 @@ func SnakeCase(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -506,7 +506,7 @@ func Wrap(str string, wrapWith string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -543,7 +543,7 @@ func Unwrap(str string, wrapToken string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {

View File

@@ -5,7 +5,7 @@ strutil包含处理字符串的相关函数。
## 源码:
[https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go)
- [https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ strutil包含处理字符串的相关函数。
## 用法:
```go
import (
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
```
@@ -58,7 +58,7 @@ func After(s, char string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -88,7 +88,7 @@ func AfterLast(s, char string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -119,7 +119,7 @@ func Before(s, char string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -150,7 +150,7 @@ func BeforeLast(s, char string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -181,7 +181,7 @@ func CamelCase(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -215,7 +215,7 @@ func Capitalize(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -238,14 +238,14 @@ func main() {
<b>函数签名:</b>
```go
func IsString(v interface{}) bool
func IsString(v any) bool
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -273,7 +273,7 @@ func KebabCase(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -307,7 +307,7 @@ func LowerFirst(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -341,7 +341,7 @@ func UpperFirst(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -375,7 +375,7 @@ func PadEnd(source string, size int, padStr string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -409,7 +409,7 @@ func PadStart(source string, size int, padStr string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -443,7 +443,7 @@ func ReverseStr(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -470,7 +470,7 @@ func SnakeCase(s string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -507,7 +507,7 @@ func Wrap(str string, wrapWith string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
@@ -544,7 +544,7 @@ func Unwrap(str string, wrapToken string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {

View File

@@ -5,7 +5,7 @@ Package system contains some functions about os, runtime, shell command.
## Source:
[https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
- [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ Package system contains some functions about os, runtime, shell command.
## Usage:
```go
import (
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
```
@@ -48,7 +48,7 @@ func IsWindows() bool
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -73,7 +73,7 @@ func IsLinux() bool
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -97,7 +97,7 @@ func IsMac() bool
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -121,7 +121,7 @@ func GetOsEnv(key string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -145,7 +145,7 @@ func SetOsEnv(key, value string) error
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -170,7 +170,7 @@ func RemoveOsEnv(key string) error
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -196,7 +196,7 @@ func CompareOsEnv(key, comparedEnv string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -222,7 +222,7 @@ func ExecCommand(command string) (stdout, stderr string, err error)
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {

View File

@@ -5,7 +5,7 @@ system包含os, runtime, shell command相关函数。
## 源码:
[https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
- [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ system包含os, runtime, shell command相关函数。
## 用法:
```go
import (
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
```
@@ -48,7 +48,7 @@ func IsWindows() bool
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -73,7 +73,7 @@ func IsLinux() bool
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -97,7 +97,7 @@ func IsMac() bool
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -121,7 +121,7 @@ func GetOsEnv(key string) string
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -145,7 +145,7 @@ func SetOsEnv(key, value string) error
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -170,7 +170,7 @@ func RemoveOsEnv(key string) error
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -196,7 +196,7 @@ func CompareOsEnv(key, comparedEnv string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {
@@ -222,7 +222,7 @@ func ExecCommand(command string) (stdout, stderr string, err error)
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
"github.com/duke-git/lancet/v2/system"
)
func main() {

View File

@@ -5,7 +5,7 @@ Package validator contains some functions for data validation.
## Source:
[https://github.com/duke-git/lancet/blob/main/validator/validator.go](https://github.com/duke-git/lancet/blob/main/validator/validator.go)
- [https://github.com/duke-git/lancet/blob/main/validator/validator.go](https://github.com/duke-git/lancet/blob/main/validator/validator.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ Package validator contains some functions for data validation.
## Usage:
```go
import (
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
```
@@ -67,7 +67,7 @@ func ContainChinese(s string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -97,7 +97,7 @@ func ContainLetter(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -128,7 +128,7 @@ func ContainLower(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -159,7 +159,7 @@ func ContainUpper(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -190,7 +190,7 @@ func IsAlpha(s string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -218,7 +218,7 @@ func IsAllUpper(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -246,7 +246,7 @@ func IsAllLower(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -274,7 +274,7 @@ func IsBase64(base64 string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -302,7 +302,7 @@ func IsChineseMobile(mobileNum string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -329,7 +329,7 @@ func IsChineseIdNum(id string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -357,7 +357,7 @@ func IsChinesePhone(phone string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -385,7 +385,7 @@ func IsCreditCard(creditCart string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -413,7 +413,7 @@ func IsDns(dns string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -444,7 +444,7 @@ func IsEmail(email string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -473,7 +473,7 @@ func IsEmptyString(s string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -501,7 +501,7 @@ func IsFloatStr(s string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -530,7 +530,7 @@ func IsNumberStr(s string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -559,7 +559,7 @@ func IsJSON(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -588,7 +588,7 @@ func IsRegexMatch(s, regex string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -614,7 +614,7 @@ func IsIntStr(s string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -641,7 +641,7 @@ func IsIp(ipstr string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -668,7 +668,7 @@ func IsIpV4(ipstr string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -695,7 +695,7 @@ func IsIpV6(ipstr string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -722,7 +722,7 @@ func IsStrongPassword(password string, length int) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -750,7 +750,7 @@ func IsUrl(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -778,7 +778,7 @@ func IsWeakPassword(password string, length int) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {

View File

@@ -5,7 +5,7 @@ validator验证器包包含常用字符串格式验证函数。
## 源码:
[https://github.com/duke-git/lancet/blob/main/validator/validator.go](https://github.com/duke-git/lancet/blob/main/validator/validator.go)
- [https://github.com/duke-git/lancet/blob/main/validator/validator.go](https://github.com/duke-git/lancet/blob/main/validator/validator.go)
<div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ validator验证器包包含常用字符串格式验证函数。
## 用法:
```go
import (
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
```
@@ -67,7 +67,7 @@ func ContainChinese(s string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -97,7 +97,7 @@ func ContainLetter(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -128,7 +128,7 @@ func ContainLower(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -159,7 +159,7 @@ func ContainUpper(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -190,7 +190,7 @@ func IsAlpha(s string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -218,7 +218,7 @@ func IsAllUpper(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -246,7 +246,7 @@ func IsAllLower(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -274,7 +274,7 @@ func IsBase64(base64 string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -302,7 +302,7 @@ func IsChineseMobile(mobileNum string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -329,7 +329,7 @@ func IsChineseIdNum(id string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -357,7 +357,7 @@ func IsChinesePhone(phone string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -385,7 +385,7 @@ func IsCreditCard(creditCart string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -413,7 +413,7 @@ func IsDns(dns string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -444,7 +444,7 @@ func IsEmail(email string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -473,7 +473,7 @@ func IsEmptyString(s string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -501,7 +501,7 @@ func IsFloatStr(s string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -530,7 +530,7 @@ func IsNumberStr(s string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -559,7 +559,7 @@ func IsJSON(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -588,7 +588,7 @@ func IsRegexMatch(s, regex string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -614,7 +614,7 @@ func IsIntStr(s string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -641,7 +641,7 @@ func IsIp(ipstr string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -668,7 +668,7 @@ func IsIpV4(ipstr string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -695,7 +695,7 @@ func IsIpV6(ipstr string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -722,7 +722,7 @@ func IsStrongPassword(password string, length int) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -750,7 +750,7 @@ func IsUrl(str string) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
@@ -778,7 +778,7 @@ func IsWeakPassword(password string, length int) bool
```go
import (
"fmt"
"github.com/duke-git/lancet/validator"
"github.com/duke-git/lancet/v2/validator"
)
func main() {

57
docs/xerror.md Normal file
View File

@@ -0,0 +1,57 @@
# Xerror
Package xerror implements helpers for errors.
<div STYLE="page-break-after: always;"></div>
## Source:
- [https://github.com/duke-git/lancet/blob/main/xerror/xerror.go](https://github.com/duke-git/lancet/blob/main/xerror/xerror.go)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/xerror"
)
```
<div STYLE="page-break-after: always;"></div>
## Index
- [Unwrap](#Unwrap)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="Unwrap">Unwrap</span>
<p>Unwrap if err is nil then it returns a valid value. If err is not nil, Unwrap panics with err.</p>
<b>Signature:</b>
```go
func Unwrap[T any](val T, err error) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
_, err := strconv.Atoi("4o2")
defer func() {
v := recover()
fmt.Println(err.Error()) // err.Error() == v.(*strconv.NumError).Error()
}()
xerror.Unwrap(strconv.Atoi("4o2"))
}
```

57
docs/xerror_zh-CN.md Normal file
View File

@@ -0,0 +1,57 @@
# Xerror
xerror错误处理逻辑封装
<div STYLE="page-break-after: always;"></div>
## 源码:
- [https://github.com/duke-git/lancet/blob/main/xerror/xerror.go](https://github.com/duke-git/lancet/blob/main/xerror/xerror.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/xerror"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [Unwrap](#Unwrap)
<div STYLE="page-break-after: always;"></div>
## 文档
### <span id="Unwrap">Unwrap</span>
<p>如果err为nil则展开则它返回一个有效值。 如果err不是nil则Unwrap使用err发生恐慌。</p>
<b>函数签名:</b>
```go
func Unwrap[T any](val T, err error) T
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
_, err := strconv.Atoi("4o2")
defer func() {
v := recover()
fmt.Println(err.Error()) // err.Error() == v.(*strconv.NumError).Error()
}()
xerror.Unwrap(strconv.Atoi("4o2"))
}
```

View File

@@ -263,7 +263,7 @@ func FileMode(path string) (fs.FileMode, error) {
// MiMeType return file mime type
// param `file` should be string(file path) or *os.File
func MiMeType(file interface{}) string {
func MiMeType(file any) string {
var mediatype string
readBuffer := func(f *os.File) ([]byte, error) {

View File

@@ -4,7 +4,7 @@ import (
"os"
"testing"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestIsExist(t *testing.T) {
@@ -76,10 +76,10 @@ func TestCopyFile(t *testing.T) {
func TestListFileNames(t *testing.T) {
assert := internal.NewAssert(t, "TestListFileNames")
filesInPath, err := ListFileNames("../datetime/")
filesInPath, err := ListFileNames("./")
assert.IsNil(err)
expected := []string{"datetime.go", "datetime_test.go"}
expected := []string{"file.go", "file_test.go"}
assert.Equal(expected, filesInPath)
}

View File

@@ -7,7 +7,7 @@ package formatter
import "strings"
// Comma add comma to number by every 3 numbers from right. ahead by symbol char
func Comma(v interface{}, symbol string) string {
func Comma(v any, symbol string) string {
s := numString(v)
dotIndex := strings.Index(s, ".")
if dotIndex != -1 {

View File

@@ -14,7 +14,7 @@ func commaString(s string) string {
return commaString(s[:len(s)-3]) + "," + commaString(s[len(s)-3:])
}
func numString(value interface{}) string {
func numString(value any) string {
switch reflect.TypeOf(value).Kind() {
case reflect.Int, reflect.Int64, reflect.Float32, reflect.Float64:
return fmt.Sprintf("%v", value)

View File

@@ -3,7 +3,7 @@ package formatter
import (
"testing"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestComma(t *testing.T) {

View File

@@ -10,11 +10,11 @@ import (
)
// After creates a function that invokes func once it's called n or more times
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
func After(n int, fn any) func(args ...any) []reflect.Value {
// Catch programming error while constructing the closure
mustBeFunction(fn)
return func(args ...interface{}) []reflect.Value {
return func(args ...any) []reflect.Value {
n--
if n < 1 {
return unsafeInvokeFunc(fn, args...)
@@ -24,11 +24,11 @@ func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
}
// Before creates a function that invokes func once it's called less than n times
func Before(n int, fn interface{}) func(args ...interface{}) []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
return func(args ...interface{}) []reflect.Value {
return func(args ...any) []reflect.Value {
if n > 0 {
res = unsafeInvokeFunc(fn, args...)
}
@@ -40,20 +40,20 @@ func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
}
}
// Fn is for curry function which is func(...interface{}) interface{}
type Fn func(...interface{}) interface{}
// Fn is for curry function which is func(...any) any
type Fn func(...any) any
// Curry make a curry function
func (f Fn) Curry(i interface{}) func(...interface{}) interface{} {
return func(values ...interface{}) interface{} {
v := append([]interface{}{i}, values...)
func (f Fn) Curry(i any) func(...any) any {
return func(values ...any) any {
v := append([]any{i}, values...)
return f(v...)
}
}
// Compose compose the functions from right to left
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{} {
return func(s ...interface{}) interface{} {
func Compose(fnList ...func(...any) any) func(...any) any {
return func(s ...any) any {
f := fnList[0]
restFn := fnList[1:]
@@ -66,7 +66,7 @@ func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) in
}
// Delay make the function execution after delayed time
func Delay(delay time.Duration, fn interface{}, args ...interface{}) {
func Delay(delay time.Duration, fn any, args ...any) {
// Catch programming error while constructing the closure
mustBeFunction(fn)
@@ -95,7 +95,7 @@ func Debounced(fn func(), duration time.Duration) func() {
}
// Schedule invoke function every duration time, util close the returned bool chan
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool {
func Schedule(d time.Duration, fn any, args ...any) chan bool {
// Catch programming error while constructing the closure
mustBeFunction(fn)

View File

@@ -5,7 +5,7 @@ import (
"reflect"
)
func invokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
func invokeFunc(fn any, args ...any) []reflect.Value {
fv := functionValue(fn)
params := make([]reflect.Value, len(args))
for i, item := range args {
@@ -14,7 +14,7 @@ func invokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
return fv.Call(params)
}
func unsafeInvokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
func unsafeInvokeFunc(fn any, args ...any) []reflect.Value {
fv := reflect.ValueOf(fn)
params := make([]reflect.Value, len(args))
for i, item := range args {
@@ -23,7 +23,7 @@ func unsafeInvokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
return fv.Call(params)
}
func functionValue(function interface{}) reflect.Value {
func functionValue(function any) reflect.Value {
v := reflect.ValueOf(function)
if v.Kind() != reflect.Func {
panic(fmt.Sprintf("Invalid function type, value of type %T", function))
@@ -31,7 +31,7 @@ func functionValue(function interface{}) reflect.Value {
return v
}
func mustBeFunction(function interface{}) {
func mustBeFunction(function any) {
v := reflect.ValueOf(function)
if v.Kind() != reflect.Func {
panic(fmt.Sprintf("Invalid function type, value of type %T", function))

View File

@@ -7,7 +7,7 @@ import (
"testing"
"time"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestAfter(t *testing.T) {
@@ -16,7 +16,7 @@ func TestAfter(t *testing.T) {
fmt.Println("print done")
return i
})
type cb func(args ...interface{}) []reflect.Value
type cb func(args ...any) []reflect.Value
print := func(i int, s string, fn cb) {
fmt.Printf("print: arr[%d] is %s \n", i, s)
v := fn(i)
@@ -42,7 +42,7 @@ func TestBefore(t *testing.T) {
})
var res []int64
type cb func(args ...interface{}) []reflect.Value
type cb func(args ...any) []reflect.Value
appendStr := func(i int, s string, fn cb) {
v := fn(i)
res = append(res, v[0].Int())
@@ -62,7 +62,7 @@ func TestCurry(t *testing.T) {
add := func(a, b int) int {
return a + b
}
var addCurry Fn = func(values ...interface{}) interface{} {
var addCurry Fn = func(values ...any) any {
return add(values[0].(int), values[1].(int))
}
add1 := addCurry.Curry(1)
@@ -72,10 +72,10 @@ func TestCurry(t *testing.T) {
func TestCompose(t *testing.T) {
assert := internal.NewAssert(t, "TestCompose")
toUpper := func(a ...interface{}) interface{} {
toUpper := func(a ...any) any {
return strings.ToUpper(a[0].(string))
}
toLower := func(a ...interface{}) interface{} {
toLower := func(a ...any) any {
return strings.ToLower(a[0].(string))
}

View File

@@ -3,7 +3,7 @@ package function
import (
"testing"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestWatcher(t *testing.T) {

4
go.mod
View File

@@ -1,3 +1,3 @@
module github.com/duke-git/lancet
module github.com/duke-git/lancet/v2
go 1.16
go 1.18

View File

@@ -30,14 +30,14 @@ func NewAssert(t *testing.T, caseName string) *Assert {
}
// Equal check if expected is equal with actual
func (a *Assert) Equal(expected, actual interface{}) {
func (a *Assert) Equal(expected, actual any) {
if compare(expected, actual) != compareEqual {
makeTestFailed(a.T, a.CaseName, expected, actual)
}
}
// NotEqual check if expected is not equal with actual
func (a *Assert) NotEqual(expected, actual interface{}) {
func (a *Assert) NotEqual(expected, actual any) {
if compare(expected, actual) == compareEqual {
expectedInfo := fmt.Sprintf("not %v", expected)
makeTestFailed(a.T, a.CaseName, expectedInfo, actual)
@@ -45,7 +45,7 @@ func (a *Assert) NotEqual(expected, actual interface{}) {
}
// Greater check if expected is greate than actual
func (a *Assert) Greater(expected, actual interface{}) {
func (a *Assert) Greater(expected, actual any) {
if compare(expected, actual) != compareGreater {
expectedInfo := fmt.Sprintf("> %v", expected)
makeTestFailed(a.T, a.CaseName, expectedInfo, actual)
@@ -53,7 +53,7 @@ func (a *Assert) Greater(expected, actual interface{}) {
}
// GreaterOrEqual check if expected is greate than or equal with actual
func (a *Assert) GreaterOrEqual(expected, actual interface{}) {
func (a *Assert) GreaterOrEqual(expected, actual any) {
isGreatOrEqual := compare(expected, actual) == compareGreater || compare(expected, actual) == compareEqual
if !isGreatOrEqual {
expectedInfo := fmt.Sprintf(">= %v", expected)
@@ -62,7 +62,7 @@ func (a *Assert) GreaterOrEqual(expected, actual interface{}) {
}
// Less check if expected is less than actual
func (a *Assert) Less(expected, actual interface{}) {
func (a *Assert) Less(expected, actual any) {
if compare(expected, actual) != compareLess {
expectedInfo := fmt.Sprintf("< %v", expected)
makeTestFailed(a.T, a.CaseName, expectedInfo, actual)
@@ -70,7 +70,7 @@ func (a *Assert) Less(expected, actual interface{}) {
}
// LessOrEqual check if expected is less than or equal with actual
func (a *Assert) LessOrEqual(expected, actual interface{}) {
func (a *Assert) LessOrEqual(expected, actual any) {
isLessOrEqual := compare(expected, actual) == compareLess || compare(expected, actual) == compareEqual
if !isLessOrEqual {
expectedInfo := fmt.Sprintf("<= %v", expected)
@@ -79,14 +79,14 @@ func (a *Assert) LessOrEqual(expected, actual interface{}) {
}
// IsNil check if value is nil
func (a *Assert) IsNil(value interface{}) {
func (a *Assert) IsNil(value any) {
if value != nil {
makeTestFailed(a.T, a.CaseName, nil, value)
}
}
// IsNotNil check if value is not nil
func (a *Assert) IsNotNil(value interface{}) {
func (a *Assert) IsNotNil(value any) {
if value == nil {
makeTestFailed(a.T, a.CaseName, "not nil", value)
}
@@ -94,7 +94,7 @@ func (a *Assert) IsNotNil(value interface{}) {
// compare x and y return :
// x > y -> 1, x < y -> -1, x == y -> 0, x != y -> -2
func compare(x, y interface{}) int {
func compare(x, y any) int {
vx := reflect.ValueOf(x)
vy := reflect.ValueOf(y)
@@ -163,7 +163,7 @@ func compare(x, y interface{}) int {
}
// logFailedInfo make test failed and log error info
func makeTestFailed(t *testing.T, caseName string, expected, actual interface{}) {
func makeTestFailed(t *testing.T, caseName string, expected, actual any) {
_, file, line, _ := runtime.Caller(2)
errInfo := fmt.Sprintf("Case %v failed. file: %v, line: %v, expected: %v, actual: %v.", caseName, file, line, expected, actual)
t.Error(errInfo)

View File

@@ -0,0 +1,18 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package lancetconstraints contain some comstomer constraints.
package lancetconstraints
// Comparator is for comparing two values
type Comparator interface {
// Compare v1 and v2
// Ascending order: should return 1 -> v1 > v2, 0 -> v1 = v2, -1 -> v1 < v2
// Descending order: should return 1 -> v1 < v2, 0 -> v1 = v2, -1 -> v1 > v2
Compare(v1, v2 any) int
}
// Number contains all types of number and uintptr, used for generics constraint
type Number interface {
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | uintptr | float32 | float64
}

107
maputil/map.go Normal file
View File

@@ -0,0 +1,107 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package maputil includes some functions to manipulate map.
package maputil
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))
for k := range m {
keys = append(keys, k)
}
return keys
}
// 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))
for _, v := range m {
values = append(values, v)
}
return values
}
// 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)
for _, m := range maps {
for k, v := range m {
res[k] = v
}
}
return res
}
// ForEach executes iteratee funcation for every key and value pair in map
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V)) {
for k, v := range m {
iteratee(k, 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)
for k, v := range m {
if predicate(k, v) {
res[k] = v
}
}
return res
}
// Intersect iterates over maps, return a new map of key and value pairs in all given maps
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
if len(maps) == 0 {
return map[K]V{}
}
if len(maps) == 1 {
return maps[0]
}
res := make(map[K]V)
reducer := func(m1, m2 map[K]V) map[K]V {
m := make(map[K]V)
for k, v1 := range m1 {
if v2, ok := m2[k]; ok && reflect.DeepEqual(v1, v2) {
m[k] = v1
}
}
return m
}
reduceMaps := make([]map[K]V, 2, 2)
res = reducer(maps[0], maps[1])
for i := 2; i < len(maps); i++ {
reduceMaps[0] = res
reduceMaps[1] = maps[i]
res = reducer(reduceMaps[0], reduceMaps[1])
}
return res
}
// 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)
for k, v := range mapA {
if _, ok := mapB[k]; !ok {
res[k] = v
}
}
return res
}

150
maputil/map_test.go Normal file
View File

@@ -0,0 +1,150 @@
package maputil
import (
"sort"
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestKeys(t *testing.T) {
assert := internal.NewAssert(t, "TestKeys")
m := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
}
keys := Keys(m)
sort.Ints(keys)
assert.Equal([]int{1, 2, 3, 4, 5}, keys)
}
func TestValues(t *testing.T) {
assert := internal.NewAssert(t, "TestValues")
m := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
}
values := Values(m)
sort.Strings(values)
assert.Equal([]string{"a", "a", "b", "c", "d"}, values)
}
func TestMerge(t *testing.T) {
assert := internal.NewAssert(t, "TestMerge")
m1 := map[int]string{
1: "a",
2: "b",
}
m2 := map[int]string{
1: "1",
3: "2",
}
expected := map[int]string{
1: "1",
2: "b",
3: "2",
}
acturl := Merge(m1, m2)
assert.Equal(expected, acturl)
}
func TestForEach(t *testing.T) {
assert := internal.NewAssert(t, "TestForEach")
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
}
var sum int
ForEach(m, func(_ string, value int) {
sum += value
})
assert.Equal(10, sum)
}
func TestFilter(t *testing.T) {
assert := internal.NewAssert(t, "TestFilter")
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
isEven := func(_ string, value int) bool {
return value%2 == 0
}
acturl := Filter(m, isEven)
assert.Equal(map[string]int{
"b": 2,
"d": 4,
}, acturl)
}
func TestIntersect(t *testing.T) {
assert := internal.NewAssert(t, "TestIntersect")
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[string]int{
"a": 1,
"b": 2,
"c": 6,
"d": 7,
}
m3 := map[string]int{
"a": 1,
"b": 9,
"e": 9,
}
assert.Equal(map[string]int{"a": 1, "b": 2, "c": 3}, Intersect(m1))
assert.Equal(map[string]int{"a": 1, "b": 2}, Intersect(m1, m2))
assert.Equal(map[string]int{"a": 1}, Intersect(m1, m2, m3))
}
func TestMinus(t *testing.T) {
assert := internal.NewAssert(t, "TestMinus")
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[string]int{
"a": 11,
"b": 22,
"d": 33,
}
assert.Equal(map[string]int{"c": 3}, Minus(m1, m2))
}

View File

@@ -9,6 +9,8 @@ import (
"math"
"strconv"
"strings"
"github.com/duke-git/lancet/v2/lancetconstraints"
)
// Exponent calculate x^n
@@ -90,3 +92,40 @@ func TruncRound(x float64, n int) float64 {
res, _ := strconv.ParseFloat(newFloat, 64)
return res
}
// Max return max value of params
func Max[T lancetconstraints.Number](numbers ...T) T {
max := numbers[0]
for _, v := range numbers {
if max < v {
max = v
}
}
return max
}
// Min return min value of params
func Min[T lancetconstraints.Number](numbers ...T) T {
min := numbers[0]
for _, v := range numbers {
if min > v {
min = v
}
}
return min
}
// Average return average value of params
func Average[T lancetconstraints.Number](numbers ...T) T {
var sum T
n := T(len(numbers))
for _, v := range numbers {
sum += v
}
return sum / n
}

View File

@@ -3,7 +3,7 @@ package mathutil
import (
"testing"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestExponent(t *testing.T) {
@@ -70,3 +70,29 @@ func TestTruncRound(t *testing.T) {
assert.Equal(TruncRound(0.125, 3), float64(0.125))
assert.Equal(TruncRound(33.33333, 2), float64(33.33))
}
func TestAverage(t *testing.T) {
assert := internal.NewAssert(t, "TestAverage")
assert.Equal(Average(0, 0), 0)
assert.Equal(Average(1, 1), 1)
avg := Average(1.2, 1.4)
t.Log(avg)
assert.Equal(1.3, RoundToFloat(avg, 1))
}
func TestMax(t *testing.T) {
assert := internal.NewAssert(t, "TestMax")
assert.Equal(Max(0, 0), 0)
assert.Equal(Max(1, 2, 3), 3)
assert.Equal(Max(1.2, 1.4, 1.1, 1.4), 1.4)
}
func TestMin(t *testing.T) {
assert := internal.NewAssert(t, "TestMin")
assert.Equal(Min(0, 0), 0)
assert.Equal(Min(1, 2, 3), 1)
assert.Equal(Min(1.2, 1.4, 1.1, 1.4), 1.1)
}

View File

@@ -6,7 +6,7 @@
// 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]interface{},
// params[1] is query param which type should be url.Values or map[string]any,
// params[2] is post body which type should be []byte.
// params[3] is http client which type should be http.Client.
package netutil
@@ -21,32 +21,32 @@ import (
)
//HttpGet send get http request
func HttpGet(url string, params ...interface{}) (*http.Response, error) {
func HttpGet(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodGet, url, params...)
}
//HttpPost send post http request
func HttpPost(url string, params ...interface{}) (*http.Response, error) {
func HttpPost(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodPost, url, params...)
}
//HttpPut send put http request
func HttpPut(url string, params ...interface{}) (*http.Response, error) {
func HttpPut(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodPut, url, params...)
}
//HttpDelete send delete http request
func HttpDelete(url string, params ...interface{}) (*http.Response, error) {
func HttpDelete(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodDelete, url, params...)
}
// HttpPatch send patch http request
func HttpPatch(url string, params ...interface{}) (*http.Response, error) {
func HttpPatch(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodPatch, url, params...)
}
// ParseHttpResponse decode http response to specified interface
func ParseHttpResponse(resp *http.Response, obj interface{}) error {
func ParseHttpResponse(resp *http.Response, obj any) error {
if resp == nil {
return errors.New("InvalidResp")
}
@@ -55,7 +55,7 @@ func ParseHttpResponse(resp *http.Response, obj interface{}) error {
}
// ConvertMapToQueryString convert map to sorted url query string
func ConvertMapToQueryString(param map[string]interface{}) string {
func ConvertMapToQueryString(param map[string]any) string {
if param == nil {
return ""
}

View File

@@ -6,7 +6,7 @@ import (
"log"
"testing"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestHttpGet(t *testing.T) {
@@ -104,7 +104,7 @@ func TestHttpDelete(t *testing.T) {
func TestConvertMapToQueryString(t *testing.T) {
assert := internal.NewAssert(t, "TestConvertMapToQueryString")
var m = map[string]interface{}{
var m = map[string]any{
"c": 3,
"a": 1,
"b": 2,

View File

@@ -10,7 +10,7 @@ import (
"strings"
)
func doHttpRequest(method, reqUrl string, params ...interface{}) (*http.Response, error) {
func doHttpRequest(method, reqUrl string, params ...any) (*http.Response, error) {
if len(reqUrl) == 0 {
return nil, errors.New("url should be specified")
}
@@ -60,7 +60,7 @@ func doHttpRequest(method, reqUrl string, params ...interface{}) (*http.Response
return resp, e
}
func setHeaderAndQueryParam(req *http.Request, reqUrl string, header, queryParam interface{}) error {
func setHeaderAndQueryParam(req *http.Request, reqUrl string, header, queryParam any) error {
err := setHeader(req, header)
if err != nil {
return err
@@ -72,7 +72,7 @@ func setHeaderAndQueryParam(req *http.Request, reqUrl string, header, queryParam
return nil
}
func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryParam, body interface{}) error {
func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryParam, body any) error {
err := setHeader(req, header)
if err != nil {
return err
@@ -88,7 +88,7 @@ func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryPar
return nil
}
func setHeader(req *http.Request, header interface{}) error {
func setHeader(req *http.Request, header any) error {
if header != nil {
switch v := header.(type) {
case map[string]string:
@@ -122,11 +122,11 @@ func setUrl(req *http.Request, reqUrl string) error {
return nil
}
func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) error {
func setQueryParam(req *http.Request, reqUrl string, queryParam any) error {
var values url.Values
if queryParam != nil {
switch v := queryParam.(type) {
case map[string]interface{}:
case map[string]any:
values = url.Values{}
for k := range v {
values.Set(k, fmt.Sprintf("%v", v[k]))
@@ -134,7 +134,7 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) err
case url.Values:
values = v
default:
return errors.New("query params type should be url.Values or map[string]interface{}")
return errors.New("query params type should be url.Values or map[string]any")
}
}
@@ -155,7 +155,7 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) err
return nil
}
func setBodyByte(req *http.Request, body interface{}) error {
func setBodyByte(req *http.Request, body any) error {
if body != nil {
switch b := body.(type) {
case []byte:
@@ -168,7 +168,7 @@ func setBodyByte(req *http.Request, body interface{}) error {
return nil
}
func getClient(client interface{}) (*http.Client, error) {
func getClient(client any) (*http.Client, error) {
c := http.Client{}
if client != nil {
switch v := client.(type) {

View File

@@ -4,7 +4,7 @@ import (
"net"
"testing"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestGetInternalIp(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"regexp"
"testing"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestRandString(t *testing.T) {

View File

@@ -6,7 +6,7 @@ import (
"testing"
"time"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestRetryFailed(t *testing.T) {

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ import (
)
// sliceValue return the reflect value of a slice
func sliceValue(slice interface{}) reflect.Value {
func sliceValue(slice any) reflect.Value {
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
panic(fmt.Sprintf("Invalid slice type, value of type %T", slice))
@@ -15,7 +15,7 @@ func sliceValue(slice interface{}) reflect.Value {
}
// functionValue return the reflect value of a function
func functionValue(function interface{}) reflect.Value {
func functionValue(function any) reflect.Value {
v := reflect.ValueOf(function)
if v.Kind() != reflect.Func {
panic(fmt.Sprintf("Invalid function type, value of type %T", function))

View File

@@ -1,10 +1,10 @@
package slice
import (
"reflect"
"math"
"testing"
"github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/v2/internal"
)
func TestContain(t *testing.T) {
@@ -15,41 +15,36 @@ func TestContain(t *testing.T) {
assert.Equal(true, Contain([]string{""}, ""))
assert.Equal(false, Contain([]string{}, ""))
var m = map[string]int{"a": 1}
assert.Equal(true, Contain(m, "a"))
assert.Equal(false, Contain(m, "b"))
assert.Equal(true, Contain("abc", "a"))
assert.Equal(false, Contain("abc", "d"))
assert.Equal(true, Contain([]int{1, 2, 3}, 1))
}
func TestContainSubSlice(t *testing.T) {
assert := internal.NewAssert(t, "TestContainSubSlice")
assert.Equal(true, ContainSubSlice([]string{"a", "a", "b", "c"}, []string{"a", "a"}))
assert.Equal(false, ContainSubSlice([]string{"a", "a", "b", "c"}, []string{"a", "d"}))
assert.Equal(true, ContainSubSlice([]int{1, 2, 3}, []int{1}))
assert.Equal(false, ContainSubSlice([]int{1, 2, 3}, []string{"a"}))
assert.Equal(true, ContainSubSlice([]int{1, 2, 3}, []int{1, 2}))
assert.Equal(false, ContainSubSlice([]int{1, 2, 3}, []int{0, 1}))
}
func TestChunk(t *testing.T) {
assert := internal.NewAssert(t, "TestChunk")
arr := []string{"a", "b", "c", "d", "e"}
r1 := [][]interface{}{{"a"}, {"b"}, {"c"}, {"d"}, {"e"}}
assert.Equal(r1, Chunk(InterfaceSlice(arr), 1))
r2 := [][]interface{}{{"a", "b"}, {"c", "d"}, {"e"}}
assert.Equal(r2, Chunk(InterfaceSlice(arr), 2))
r1 := [][]string{{"a"}, {"b"}, {"c"}, {"d"}, {"e"}}
assert.Equal(r1, Chunk(arr, 1))
r3 := [][]interface{}{{"a", "b", "c"}, {"d", "e"}}
assert.Equal(r3, Chunk(InterfaceSlice(arr), 3))
r2 := [][]string{{"a", "b"}, {"c", "d"}, {"e"}}
assert.Equal(r2, Chunk(arr, 2))
r4 := [][]interface{}{{"a", "b", "c", "d"}, {"e"}}
assert.Equal(r4, Chunk(InterfaceSlice(arr), 4))
r3 := [][]string{{"a", "b", "c"}, {"d", "e"}}
assert.Equal(r3, Chunk(arr, 3))
r5 := [][]interface{}{{"a"}, {"b"}, {"c"}, {"d"}, {"e"}}
assert.Equal(r5, Chunk(InterfaceSlice(arr), 5))
r4 := [][]string{{"a", "b", "c", "d"}, {"e"}}
assert.Equal(r4, Chunk(arr, 4))
r5 := [][]string{{"a"}, {"b"}, {"c"}, {"d"}, {"e"}}
assert.Equal(r5, Chunk(arr, 5))
}
func TestCompact(t *testing.T) {
@@ -66,11 +61,11 @@ 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{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))
// assert.Equal([]int{1, 2, 3, 4, 5}, Concat([]int{1, 2, 3}, []int{4}, 5))
}
func TestEvery(t *testing.T) {
@@ -148,6 +143,20 @@ func TestGroupBy(t *testing.T) {
assert.Equal(expectedOdd, odd)
}
func TestGroupWith(t *testing.T) {
nums := []float64{6.1, 4.2, 6.3}
floor := func(num float64) float64 {
return math.Floor(num)
}
expected := map[float64][]float64{
4: {4.2},
6: {6.1, 6.3},
}
actual := GroupWith(nums, floor)
assert := internal.NewAssert(t, "TestGroupWith")
assert.Equal(expected, actual)
}
func TestCount(t *testing.T) {
nums := []int{1, 2, 3, 4, 5, 6}
evenFunc := func(i, num int) bool {
@@ -169,7 +178,7 @@ func TestFind(t *testing.T) {
}
assert := internal.NewAssert(t, "TestFind")
assert.Equal(2, res)
assert.Equal(2, *res)
}
func TestFindLast(t *testing.T) {
@@ -183,7 +192,7 @@ func TestFindLast(t *testing.T) {
}
assert := internal.NewAssert(t, "TestFindLast")
assert.Equal(4, res)
assert.Equal(4, *res)
}
func TestFindFoundNothing(t *testing.T) {
@@ -212,9 +221,11 @@ func TestForEach(t *testing.T) {
expected := []int{3, 4, 5, 6, 7}
var numbersAddTwo []int
ForEach(numbers, func(index int, value int) {
addTwo := func(index int, value int) {
numbersAddTwo = append(numbersAddTwo, value+2)
})
}
ForEach(numbers, addTwo)
assert := internal.NewAssert(t, "TestForEach")
assert.Equal(expected, numbersAddTwo)
@@ -272,7 +283,7 @@ func TestReduce(t *testing.T) {
}
func TestIntSlice(t *testing.T) {
var nums []interface{}
var nums []any
nums = append(nums, 1, 2, 3)
assert := internal.NewAssert(t, "TestIntSlice")
@@ -280,7 +291,7 @@ func TestIntSlice(t *testing.T) {
}
func TestStringSlice(t *testing.T) {
var strs []interface{}
var strs []any
strs = append(strs, "a", "b", "c")
assert := internal.NewAssert(t, "TestStringSlice")
@@ -289,41 +300,27 @@ func TestStringSlice(t *testing.T) {
func TestInterfaceSlice(t *testing.T) {
strs := []string{"a", "b", "c"}
expect := []interface{}{"a", "b", "c"}
expect := []any{"a", "b", "c"}
assert := internal.NewAssert(t, "TestInterfaceSlice")
assert.Equal(expect, InterfaceSlice(strs))
}
func TestDeleteByIndex(t *testing.T) {
assert := internal.NewAssert(t, "TestDeleteByIndex")
func TestDeleteAt(t *testing.T) {
assert := internal.NewAssert(t, "TestDeleteAt")
t1 := []string{"a", "b", "c", "d", "e"}
r1 := []string{"b", "c", "d", "e"}
a1, _ := DeleteByIndex(t1, 0)
assert.Equal(r1, a1)
assert.Equal([]string{"a", "b", "c"}, DeleteAt([]string{"a", "b", "c"}, -1))
assert.Equal([]string{"a", "b", "c"}, DeleteAt([]string{"a", "b", "c"}, 3))
assert.Equal([]string{"b", "c"}, DeleteAt([]string{"a", "b", "c"}, 0))
assert.Equal([]string{"a", "c"}, DeleteAt([]string{"a", "b", "c"}, 1))
assert.Equal([]string{"a", "b"}, DeleteAt([]string{"a", "b", "c"}, 2))
t2 := []string{"a", "b", "c", "d", "e"}
r2 := []string{"a", "b", "c", "e"}
a2, _ := DeleteByIndex(t2, 3)
assert.Equal(r2, a2)
t3 := []string{"a", "b", "c", "d", "e"}
r3 := []string{"c", "d", "e"}
a3, _ := DeleteByIndex(t3, 0, 2)
assert.Equal(r3, a3)
t4 := []string{"a", "b", "c", "d", "e"}
r4 := []string{}
a4, _ := DeleteByIndex(t4, 0, 5)
assert.Equal(r4, a4)
t5 := []string{"a", "b", "c", "d", "e"}
_, err := DeleteByIndex(t5, 1, 1)
assert.IsNotNil(err)
_, err = DeleteByIndex(t5, 0, 6)
assert.IsNotNil(err)
assert.Equal([]string{"b", "c"}, DeleteAt([]string{"a", "b", "c"}, 0, 1))
assert.Equal([]string{"c"}, DeleteAt([]string{"a", "b", "c"}, 0, 2))
assert.Equal([]string{}, DeleteAt([]string{"a", "b", "c"}, 0, 3))
assert.Equal([]string{}, DeleteAt([]string{"a", "b", "c"}, 0, 4))
assert.Equal([]string{"a"}, DeleteAt([]string{"a", "b", "c"}, 1, 3))
assert.Equal([]string{"a"}, DeleteAt([]string{"a", "b", "c"}, 1, 4))
}
func TestDrop(t *testing.T) {
@@ -343,48 +340,28 @@ func TestDrop(t *testing.T) {
assert.Equal([]int{}, Drop([]int{1, 2, 3, 4, 5}, -6))
}
func TestInsertByIndex(t *testing.T) {
assert := internal.NewAssert(t, "TestInsertByIndex")
func TestInsertAt(t *testing.T) {
assert := internal.NewAssert(t, "TestInsertAt")
t1 := []string{"a", "b", "c"}
r1, _ := InsertByIndex(t1, 0, "1")
assert.Equal([]string{"1", "a", "b", "c"}, r1)
r2, _ := InsertByIndex(t1, 1, "1")
assert.Equal([]string{"a", "1", "b", "c"}, r2)
r3, _ := InsertByIndex(t1, 3, "1")
assert.Equal([]string{"a", "b", "c", "1"}, r3)
r4, _ := InsertByIndex(t1, 0, []string{"1", "2", "3"})
assert.Equal([]string{"1", "2", "3", "a", "b", "c"}, r4)
r5, _ := InsertByIndex(t1, 3, []string{"1", "2", "3"})
assert.Equal([]string{"a", "b", "c", "1", "2", "3"}, r5)
_, err := InsertByIndex(t1, 4, "1")
assert.IsNotNil(err)
_, err = InsertByIndex(t1, 0, 1)
assert.IsNotNil(err)
strs := []string{"a", "b", "c"}
assert.Equal([]string{"a", "b", "c"}, InsertAt(strs, -1, "1"))
assert.Equal([]string{"a", "b", "c"}, InsertAt(strs, 4, "1"))
assert.Equal([]string{"1", "a", "b", "c"}, InsertAt(strs, 0, "1"))
assert.Equal([]string{"a", "1", "b", "c"}, InsertAt(strs, 1, "1"))
assert.Equal([]string{"a", "b", "1", "c"}, InsertAt(strs, 2, "1"))
assert.Equal([]string{"a", "b", "c", "1"}, InsertAt(strs, 3, "1"))
assert.Equal([]string{"1", "2", "3", "a", "b", "c"}, InsertAt(strs, 0, []string{"1", "2", "3"}))
assert.Equal([]string{"a", "b", "c", "1", "2", "3"}, InsertAt(strs, 3, []string{"1", "2", "3"}))
t.Log(strs)
}
func TestUpdateByIndex(t *testing.T) {
assert := internal.NewAssert(t, "TestUpdateByIndex")
func TestUpdateAt(t *testing.T) {
assert := internal.NewAssert(t, "TestUpdateAt")
t1 := []string{"a", "b", "c"}
r1, _ := UpdateByIndex(t1, 0, "1")
assert.Equal([]string{"1", "b", "c"}, r1)
t2 := []string{"a", "b", "c"}
r2, _ := UpdateByIndex(t2, 1, "1")
assert.Equal([]string{"a", "1", "c"}, r2)
_, err := UpdateByIndex([]string{"a", "b", "c"}, 4, "1")
assert.IsNotNil(err)
_, err = UpdateByIndex([]string{"a", "b", "c"}, 0, 1)
assert.IsNotNil(err)
assert.Equal([]string{"a", "b", "c"}, UpdateAt([]string{"a", "b", "c"}, -1, "1"))
assert.Equal([]string{"1", "b", "c"}, UpdateAt([]string{"a", "b", "c"}, 0, "1"))
assert.Equal([]string{"a", "b", "2"}, UpdateAt([]string{"a", "b", "c"}, 2, "2"))
assert.Equal([]string{"a", "b", "c"}, UpdateAt([]string{"a", "b", "c"}, 3, "2"))
}
func TestUnique(t *testing.T) {
@@ -418,7 +395,7 @@ func TestIntersection(t *testing.T) {
{1, 2, 3},
{},
}
res := []interface{}{
res := []any{
Intersection(s1, s2, s3),
Intersection(s1, s2),
Intersection(s1),
@@ -428,20 +405,31 @@ func TestIntersection(t *testing.T) {
assert := internal.NewAssert(t, "TestIntersection")
for i := 0; i < len(res); i++ {
assert.Equal(res[i], expected[i])
assert.Equal(expected[i], res[i])
}
assert.IsNil(Intersection())
}
func TestReverseSlice(t *testing.T) {
assert := internal.NewAssert(t, "TestIntersection")
func TestSymmetricDifference(t *testing.T) {
assert := internal.NewAssert(t, "TestSymmetricDifference")
s1 := []int{1, 2, 3}
s2 := []int{1, 2, 4}
s3 := []int{1, 2, 3, 5}
assert.Equal([]int{1, 2, 3}, SymmetricDifference(s1))
assert.Equal([]int{3, 4}, SymmetricDifference(s1, s2))
assert.Equal([]int{3, 4, 5}, SymmetricDifference(s1, s2, s3))
}
func TestReverse(t *testing.T) {
assert := internal.NewAssert(t, "TestReverse")
s1 := []int{1, 2, 3, 4, 5}
ReverseSlice(s1)
Reverse(s1)
assert.Equal([]int{5, 4, 3, 2, 1}, s1)
s2 := []string{"a", "b", "c", "d", "e"}
ReverseSlice(s2)
Reverse(s2)
assert.Equal([]string{"e", "d", "c", "b", "a"}, s2)
}
@@ -453,6 +441,17 @@ func TestDifference(t *testing.T) {
assert.Equal([]int{1, 2, 3}, Difference(s1, s2))
}
func TestDifferenceWith(t *testing.T) {
assert := internal.NewAssert(t, "TestDifferenceWith")
s1 := []int{1, 2, 3, 4, 5}
s2 := []int{4, 5, 6, 7, 8}
isDouble := func(v1, v2 int) bool {
return v2 == 2*v1
}
assert.Equal([]int{1, 5}, DifferenceWith(s1, s2, isDouble))
}
func TestDifferenceBy(t *testing.T) {
assert := internal.NewAssert(t, "TestDifferenceBy")
@@ -529,17 +528,5 @@ func TestShuffle(t *testing.T) {
res := Shuffle(s)
t.Log("Shuffle result: ", res)
assert.Equal(reflect.TypeOf(s), reflect.TypeOf(res))
rv := reflect.ValueOf(res)
assert.Equal(5, rv.Len())
assert.Equal(true, rv.Kind() == reflect.Slice)
assert.Equal(true, rv.Type().Elem().Kind() == reflect.Int)
assert.Equal(true, Contain(res, 1))
assert.Equal(true, Contain(res, 2))
assert.Equal(true, Contain(res, 3))
assert.Equal(true, Contain(res, 4))
assert.Equal(true, Contain(res, 5))
assert.Equal(5, len(res))
}

View File

@@ -1,4 +1,3 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package strutil implements some functions to manipulate string.
@@ -197,7 +196,7 @@ func AfterLast(s, char string) string {
}
// IsString check if the value data type is string or not.
func IsString(v interface{}) bool {
func IsString(v any) bool {
if v == nil {
return false
}

Some files were not shown because too many files have changed in this diff Show More