1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-03-01 00:35:28 +08:00

Compare commits

..

17 Commits

Author SHA1 Message Date
dudaodong
4ffff0e3f3 update pem file 2024-12-04 11:26:49 +08:00
dudaodong
8ebb8a028e doc: update doc for v2.3.4 2024-12-04 11:24:53 +08:00
dudaodong
995ffb799f fix: github action failed 2024-12-02 17:19:47 +08:00
dudaodong
3cd546d7f2 fix: fix issue #274 2024-12-02 17:06:06 +08:00
dudaodong
7fb49515ce feat: add ToBigInt 2024-12-02 11:25:16 +08:00
dudaodong
8f3ea60636 refactoring: reimplement the logic of Intersection 2024-11-29 15:47:08 +08:00
dudaodong
58a37b7e8d Merge branch 'rc' into v2 2024-11-27 15:09:35 +08:00
dudaodong
6bd61460d3 fix: MaxInt was added only in 1.17 use instead 2024-11-27 15:08:54 +08:00
Yurun
05b85a2131 Pre-allocate memory to reduce the number of allocations (#272) 2024-11-27 14:58:02 +08:00
dudaodong
1eb793420e doc: add Gurubase and update Sponsor text 2024-11-19 10:29:41 +08:00
dudaodong
05f9854945 Merge branch 'rc' 2024-11-19 10:26:41 +08:00
dudaodong
3be706e23f doc: add doc for Permutation and Combination function 2024-11-19 10:25:32 +08:00
Kursat Aktas
b5e7312353 Introducing Lancet Guru on Gurubase.io (#271) 2024-11-19 10:21:30 +08:00
dudaodong
95a894e53f feat: add Permutation and Combination 2024-11-19 10:12:07 +08:00
dudaodong
8322951475 feat: add StdDev and fix bug of Average for math package 2024-11-18 17:01:27 +08:00
dudaodong
6b2c91b0f6 feat: add Variance for math package 2024-11-18 16:25:32 +08:00
dudaodong
ec161f335d fix: update random seed when call random function 2024-11-14 16:27:22 +08:00
37 changed files with 1267 additions and 476 deletions

View File

@@ -4,12 +4,13 @@
<br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.3.3-green.svg)](https://github.com/duke-git/lancet/releases)
[![Release](https://img.shields.io/badge/release-2.3.4-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)
[![Gurubase](https://img.shields.io/badge/Gurubase-Ask%20Lancet%20Guru-006BFF)](https://gurubase.io/g/lancet)
</div>
@@ -38,7 +39,7 @@
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
```
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.4. </b>
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.5. </b>
```go
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
@@ -320,12 +321,19 @@ import "github.com/duke-git/lancet/v2/convertor"
[[play](https://go.dev/play/p/OphmHCN_9u8)]
- **<big>ToStdBase64</big>** : converts a value to a string encoded in standard Base64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#ToStdBase64)]
[[play](https://go.dev/play/p/_fLJqJD3NMo)]
- **<big>ToUrlBase64</big>** : converts a value to a string encoded in url Base64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#ToUrlBase64)]
[[play](https://go.dev/play/p/C_d0GlvEeUR)]
- **<big>ToRawStdBase64</big>** : converts a value to a string encoded in raw standard Base64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#ToRawStdBase64)]
[[play](https://go.dev/play/p/wSAr3sfkDcv)]
- **<big>ToRawUrlBase64</big>** : converts a value to a string encoded in raw url Base64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#ToRawUrlBase64)]
[[play](https://go.dev/play/p/HwdDPFcza1O)]
- **<big>ToBigInt</big>** : converts an integer of any supported type (int, int64, uint64, etc.) to *big.Int.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#ToBigInt)]
[[play](https://go.dev/play/p/todo)]
<h3 id="cryptor"> 6. Cryptor package is for data encryption and decryption.&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -474,7 +482,12 @@ import "github.com/duke-git/lancet/v2/cryptor"
- **<big>RsaDecryptOAEP</big>** : decrypts the data with RSA-OAEP
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#RsaDecryptOAEP)]
[[play](https://go.dev/play/p/sSVmkfENKMz)]
- **<big>RsaSign</big>** : signs the data with RSA.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#RsaSign)]
[[play](https://go.dev/play/p/todo)]
- **<big>RsaVerifySign</big>** : verifies the signature of the data with RSA.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#RsaVerifySign)]
[[play](https://go.dev/play/p/todo)]
<h3 id="datetime"> 7. Datetime package supports date and time format and compare. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -618,7 +631,15 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>GenerateDatetimesBetween</big>** : returns a slice of strings between two times.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#GenerateDatetimesBetween)]
[[play](https://go.dev/play/p/6kHBpAxD9ZC)]
- **<big>Min</big>** : returns the earliest time among the given times.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#Min)]
[[play](https://go.dev/play/p/todo)]
- **<big>Max</big>** : returns the latest time among the given times.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#Max)]
[[play](https://go.dev/play/p/todo)]
- **<big>MaxMin</big>** : returns the latest and earliest time among the given times.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#MaxMin)]
[[play](https://go.dev/play/p/todo)]
<h3 id="datastructure"> 8. Datastructure package contains some common data structure. eg. list, linklist, stack, queue, set, tree, graph. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -754,6 +775,9 @@ import "github.com/duke-git/lancet/v2/fileutil"
- **<big>ParallelChunkRead</big>** : reads the file in parallel and send each chunk of lines to the specified channel.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#ParallelChunkRead)]
[[play](https://go.dev/play/p/teMXnCsdSEw)]
- **<big>GetExeOrDllVersion</big>** : Get the version of exe or dll file on windows os.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#GetExeOrDllVersion)]
[[play](https://go.dev/play/p/todo)]
<h3 id="formatter"> 10. Formatter contains some functions for data formatting. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -1119,7 +1143,18 @@ import "github.com/duke-git/lancet/v2/mathutil"
- **<big>Div</big>** : returns the result of x divided by y.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#Div)]
[[play](https://go.dev/play/p/WLxDdGXXYat)]
- **<big>Variance</big>** : returns the variance of numbers.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#Variance)]
[[play](https://go.dev/play/p/todo)]
- **<big>StdDev</big>** : returns the standard deviation of numbers.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#StdDev)]
[[play](https://go.dev/play/p/todo)]
- **<big>Permutation</big>** : calculates P(n, k).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#Permutation)]
[[play](https://go.dev/play/p/todo)]
- **<big>Combination</big>** : calculates C(n, k).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#Combination)]
[[play](https://go.dev/play/p/todo)]
<h3 id="netutil"> 14. Netutil package contains functions to get net information and send http request. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -1280,7 +1315,9 @@ import "github.com/duke-git/lancet/v2/random"
- **<big>RandSliceFromGivenSlice</big>** : generate a random slice of length num from given slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandSliceFromGivenSlice)]
[[play](https://go.dev/play/p/68UikN9d6VT)]
- **<big>RandNumberOfLength</big>** : generates a random int number of specified length.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandNumberOfLength)]
[[play](https://go.dev/play/p/todo)]
<h3 id="retry"> 17. Retry package is for executing a function repeatedly until it was successful or canceled by the context. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -1574,7 +1611,12 @@ import "github.com/duke-git/lancet/v2/slice"
- **<big>Frequency</big>** : counts the frequency of each element in the slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Frequency)]
[[play](https://go.dev/play/p/CW3UVNdUZOq)]
- **<big>JoinFunc</big>** : joins the slice elements into a single string with the given separator.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#JoinFunc)]
[[play](https://go.dev/play/p/todo)]
- **<big>ConcatBy</big>** : concats the elements of a slice into a single value using the provided separator and connector function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#ConcatBy)]
[[play](https://go.dev/play/p/todo)]
<h3 id="stream"> 19. Stream package implements a sequence of elements supporting sequential and operations. this package is an experiment to explore if stream in go can work as the way java does. its function is very limited. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -1665,6 +1707,12 @@ import "github.com/duke-git/lancet/v2/stream"
- **<big>ToSlice</big>** : returns the elements in the stream.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#ToSlice)]
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
- **<big>IndexOf</big>** : returns the index of the first occurrence of the specified element in this stream.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#IndexOf)]
[[play](https://go.dev/play/p/todo)]
- **<big>LastIndexOf</big>** : returns the index of the last occurrence of the specified element in this stream.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#LastIndexOf)]
[[play](https://go.dev/play/p/todo)]
<h3 id="structs"> 20. Structs package provides several high level functions to manipulate struct, tag, and field. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -1846,6 +1894,9 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>RegexMatchAllGroups</big>** : matches all subgroups in a string using a regular expression and returns the result.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#RegexMatchAllGroups)]
[[play](https://go.dev/play/p/JZiu0RXpgN-)]
- **<big>ExtractContent</big>** : extracts the content between the start and end strings in the source string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#ExtractContent)]
[[play](https://go.dev/play/p/todo)]
<h3 id="system"> 22. System package contain some functions about os, runtime, shell command. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -2196,6 +2247,9 @@ import "github.com/duke-git/lancet/v2/xerror"
- **<big>TryUnwrap</big>** : check if err is nil then it returns a valid value. If err is not nil, TryUnwrap panics with err.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/xerror.md#TryUnwrap)]
[[play](https://go.dev/play/p/acyZVkNZEeW)]
- **<big>TryCatch</big>** : simple simulation of Java-style try-catch.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/xerror.md#TryCatch)]
[[play](https://go.dev/play/p/todo)]
## How to Contribute

View File

@@ -4,12 +4,13 @@
<br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.3.3-green.svg)](https://github.com/duke-git/lancet/releases)
[![Release](https://img.shields.io/badge/release-2.3.4-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)
[![Gurubase](https://img.shields.io/badge/Gurubase-Ask%20Lancet%20Guru-006BFF)](https://gurubase.io/g/lancet)
</div>
@@ -37,7 +38,7 @@
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
```
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.4。</b>
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.5。</b>
```go
go get github.com/duke-git/lancet// 使用go1.18以下版本, 必须安装v1.x.x版本
@@ -320,13 +321,19 @@ import "github.com/duke-git/lancet/v2/convertor"
[[play](https://go.dev/play/p/OphmHCN_9u8)]
- **<big>ToStdBase64</big>** : 将值转换为StdBase64编码的字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToStdBase64)]
[[play](https://go.dev/play/p/_fLJqJD3NMo)]
- **<big>ToUrlBase64</big>** : 将值转换为url Base64编码的字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToUrlBase64)]
[[play](https://go.dev/play/p/C_d0GlvEeUR)]
- **<big>ToRawStdBase64</big>** : 将值转换为RawStdBase64编码的字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToRawStdBase64)]
[[play](https://go.dev/play/p/wSAr3sfkDcv)]
- **<big>ToRawUrlBase64</big>** : 将值转换为RawUrlBase64编码的字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToRawUrlBase64)]
[[play](https://go.dev/play/p/HwdDPFcza1O)]
- **<big>ToBigInt</big>** : 将整数转为*big.Int。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToBigInt)]
[[play](https://go.dev/play/p/todo)]
<h3 id="cryptor"> 6. cryptor 加密包支持数据加密和解密,获取 md5hash 值。支持 base64, md5, hmac, aes, des, rsa。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -476,7 +483,12 @@ import "github.com/duke-git/lancet/v2/cryptor"
- **<big>RsaDecryptOAEP</big>** : rsa OAEP解密。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#RsaDecryptOAEP)]
[[play](https://go.dev/play/p/sSVmkfENKMz)]
- **<big>RsaSign</big>** : 应用RSA算法签名数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#RsaSign)]
[[play](https://go.dev/play/p/todo)]
- **<big>RsaVerifySign</big>** : 验证数据的签名是否符合RSA算法。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#RsaVerifySign)]
[[play](https://go.dev/play/p/todo)]
<h3 id="datetime"> 7. datetime日期时间处理包格式化日期比较日期。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -621,6 +633,15 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>GenerateDatetimesBetween</big>** : 生成从start到end的所有日期时间的字符串列表。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#GenerateDatetimesBetween)]
[[play](https://go.dev/play/p/6kHBpAxD9ZC)]
- **<big>Min</big>** : 返回最早时间。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#Min)]
[[play](https://go.dev/play/p/todo)]
- **<big>Max</big>** : 返回最晚时间。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#Max)]
[[play](https://go.dev/play/p/todo)]
- **<big>MaxMin</big>** : 返回最早和最晚时间。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#MaxMin)]
[[play](https://go.dev/play/p/todo)]
<h3 id="datastructure"> 8. datastructure 包含一些普通的数据结构实现。例如list, linklist, stack, queue, set, tree, graph。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -753,7 +774,9 @@ import "github.com/duke-git/lancet/v2/fileutil"
- **<big>ParallelChunkRead</big>** : 并行读取文件并将每个块的行发送到指定通道。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#ParallelChunkRead)]
[[play](https://go.dev/play/p/teMXnCsdSEw)]
- **<big>GetExeOrDllVersion</big>** : 返回exe,dll文件版本号(仅Window平台)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#GetExeOrDllVersion)]
[[play](https://go.dev/play/p/todo)]
<h3 id="formatter"> 10. formatter 格式化器包含一些数据格式化处理方法。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -1120,7 +1143,18 @@ import "github.com/duke-git/lancet/v2/mathutil"
- **<big>Div</big>** : 除法运算。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#Div)]
[[play](https://go.dev/play/p/WLxDdGXXYat)]
- **<big>Variance</big>** : 计算方差。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#Variance)]
[[play](https://go.dev/play/p/todo)]
- **<big>StdDev</big>** : 计算标准差。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#StdDev)]
[[play](https://go.dev/play/p/todo)]
- **<big>Permutation</big>** : 计算排列数P(n, k)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#Permutation)]
[[play](https://go.dev/play/p/todo)]
- **<big>Combination</big>** : 计算组合数C(n, k)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#Combination)]
[[play](https://go.dev/play/p/todo)]
<h3 id="netutil"> 14. netutil 网络包支持获取 ip 地址,发送 http 请求。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -1281,7 +1315,9 @@ import "github.com/duke-git/lancet/v2/random"
- **<big>RandSliceFromGivenSlice</big>** : 从给定切片中生成长度为 num 的随机切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandSliceFromGivenSlice)]
[[play](https://go.dev/play/p/68UikN9d6VT)]
- **<big>RandNumberOfLength</big>** : 生成指定长度的随机数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandNumberOfLength)]
[[play](https://go.dev/play/p/todo)]
<h3 id="retry"> 17. retry 重试执行函数直到函数运行成功或被 context cancel。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -1300,7 +1336,7 @@ import "github.com/duke-git/lancet/v2/retry"
- **<big>RetryFunc</big>** : 重试执行的函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/retry.md#RetryFunc)]
[[play](https://go.dev/play/p/nk2XRmagfVF)]
- **<big>RetryTimes</big>** : 设置重试次数,默认 5。
- **<big>RetryTimes</big>** : 设置重试次数默认5。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/retry.md#RetryTimes)]
[[play](https://go.dev/play/p/ssfVeU2SwLO)]
- **<big>BackoffStrategy</big>** : 定义计算退避间隔的方法的接口。
@@ -1572,7 +1608,12 @@ import "github.com/duke-git/lancet/v2/slice"
- **<big>Frequency</big>** : 计算切片中每个元素出现的频率。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Frequency)]
[[play](https://go.dev/play/p/CW3UVNdUZOq)]
- **<big>JoinFunc</big>** : 将切片元素用给定的分隔符连接成一个单一的字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#JoinFunc)]
[[play](https://go.dev/play/p/todo)]
- **<big>ConcatBy</big>** : 将切片中的元素连接成一个值,使用指定的分隔符和连接器函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#ConcatBy)]
[[play](https://go.dev/play/p/todo)]
<h3 id="stream"> 19. stream 流,该包仅验证简单的 stream 实现,功能有限。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -1663,7 +1704,12 @@ import "github.com/duke-git/lancet/v2/stream"
- **<big>ToSlice</big>** : 返回 stream 中的元素切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#ToSlice)]
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
- **<big>IndexOf</big>** : 返回在stream中找到值的第一个匹配项的索引如果找不到值则返回-1。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#IndexOf)]
[[play](https://go.dev/play/p/todo)]
- **<big>LastIndexOf</big>** : 返回在stream中找到值的最后一个匹配项的索引如果找不到值则返回-1。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#LastIndexOf)]
[[play](https://go.dev/play/p/todo)]
<h3 id="structs"> 20. structs 提供操作 struct, tag, field 的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -1848,6 +1894,9 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>RegexMatchAllGroups</big>** : 使用正则表达式匹配字符串中的所有子组并返回结果。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#RegexMatchAllGroups)]
[[play](https://go.dev/play/p/JZiu0RXpgN-)]
- **<big>ExtractContent</big>** : 提取两个标记之间的内容。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#ExtractContent)]
[[play](https://go.dev/play/p/todo)]
<h3 id="system"> 22. system 包含 os, runtime, shell command 的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -2060,7 +2109,7 @@ import "github.com/duke-git/lancet/v2/validator"
- **<big>IsCreditCard</big>** : 验证字符串是否是信用卡号码。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsCreditCard)]
[[play](https://go.dev/play/p/sNwwL6B0-v4)]
- **<big>IsDns</big>** : 验证字符串是否是有效 dns。
- **<big>IsDns</big>** : 验证字符串是否是有效dns。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsDns)]
[[play](https://go.dev/play/p/jlYApVLLGTZ)]
- **<big>IsEmail</big>** : 验证字符串是否是有效电子邮件地址。
@@ -2096,10 +2145,10 @@ import "github.com/duke-git/lancet/v2/validator"
- **<big>IsIp</big>** : 验证字符串是否是 ip 地址。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsIp)]
[[play](https://go.dev/play/p/FgcplDvmxoD)]
- **<big>IsIpV4</big>** : 验证字符串是否是 ipv4 地址。
- **<big>IsIpV4</big>** : 验证字符串是否是ipv4地址。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsIpV4)]
[[play](https://go.dev/play/p/zBGT99EjaIu)]
- **<big>IsIpV6</big>** : 验证字符串是否是 ipv6 地址。
- **<big>IsIpV6</big>** : 验证字符串是否是ipv6地址。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsIpV6)]
[[play](https://go.dev/play/p/AHA0r0AzIdC)]
- **<big>IsStrongPassword</big>** : 验证字符串是否是强密码:(字母+数字+特殊字符)。
@@ -2114,10 +2163,10 @@ import "github.com/duke-git/lancet/v2/validator"
- **<big>IsZeroValue</big>** : 判断传入的参数值是否为零值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsZeroValue)]
[[play](https://go.dev/play/p/UMrwaDCi_t4)]
- **<big>IsGBK</big>** : 检查数据编码是否为 gbk汉字内部代码扩展规范
- **<big>IsGBK</big>** : 检查数据编码是否为gbk汉字内部代码扩展规范
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsGBK)]
[[play](https://go.dev/play/p/E2nt3unlmzP)]
- **<big>IsASCII</big>** : 验证字符串全部为 ASCII 字符。
- **<big>IsASCII</big>** : 验证字符串全部为ASCII字符。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsASCII)]
[[play](https://go.dev/play/p/hfQNPLX0jNa)]
- **<big>IsPrintable</big>** : 检查字符串是否全部为可打印字符。
@@ -2132,13 +2181,13 @@ import "github.com/duke-git/lancet/v2/validator"
- **<big>IsBase64URL</big>** : 检查字符串是否是有效的 base64 url。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsBase64URL)]
[[play](https://go.dev/play/p/vhl4mr8GZ6S)]
- **<big>IsJWT</big>** : 检查字符串是否是有效的 JSON Web Token (JWT)。
- **<big>IsJWT</big>** : 检查字符串是否是有效的JSON Web Token (JWT)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsJWT)]
[[play](https://go.dev/play/p/R6Op7heJbKI)]
- **<big>IsVisa</big>** : 检查字符串是否是有效的 visa 卡号。
- **<big>IsVisa</big>** : 检查字符串是否是有效的visa卡号。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsVisa)]
[[play](https://go.dev/play/p/SdS2keOyJsl)]
- **<big>IsMasterCard</big>** : 检查字符串是否是有效的 MasterCard 卡号。
- **<big>IsMasterCard</big>** : 检查字符串是否是有效的MasterCard卡号。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsMasterCard)]
[[play](https://go.dev/play/p/CwWBFRrG27b)]
- **<big>IsAmericanExpress</big>** : 检查字符串是否是有效的 American Express 卡号。
@@ -2174,30 +2223,33 @@ import "github.com/duke-git/lancet/v2/xerror"
- **<big>XError_Unwrap</big>** : 解构 XEerror 为 error 对象。适配 github.com/pkg/errors。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Unwrap)
[[play](https://go.dev/play/p/VUXJ8BST4c6)]
- **<big>XError_With</big>** : 添加与 XError 对象的键和值。
- **<big>XError_With</big>** : 添加与XError对象的键和值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_With)]
[[play](https://go.dev/play/p/ow8UISXX_Dp)]
- **<big>XError_Id</big>** : 设置 XError 对象的 id。
- **<big>XError_Id</big>** : 设置XError对象的id。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Id)]
[[play](https://go.dev/play/p/X6HBlsy58U9)]
- **<big>XError_Is</big>** : 检查目标 error 是否为 XError两个错误中的 error.id 是否匹配。
- **<big>XError_Is</big>** : 检查目标error是否为XError两个错误中的error.id是否匹配。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Is)]
[[play](https://go.dev/play/p/X6HBlsy58U9)]
- **<big>XError_Values</big>** : 返回由 With 设置的键和值的映射。将合并所有 XError 键和值。
- **<big>XError_Values</big>** : 返回由With设置的键和值的映射。将合并所有XError键和值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Values)]
[[play](https://go.dev/play/p/ow8UISXX_Dp)]
- **<big>XError_StackTrace</big>** : 返回与 pkg/error 兼容的堆栈信息。
- **<big>XError_StackTrace</big>** : 返回与pkg/error兼容的堆栈信息。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_StackTrace)]
[[play](https://go.dev/play/p/6FAvSQpa7pc)]
- **<big>XError_Info</big>** : 返回可打印的 XError 对象信息。
- **<big>XError_Info</big>** : 返回可打印的XError对象信息。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Info)]
[[play](https://go.dev/play/p/1ZX0ME1F-Jb)]
- **<big>XError_Error</big>** : 实现标准库的 error 接口。
- **<big>XError_Error</big>** : 实现标准库的error接口。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Error)]
[[play](https://go.dev/play/p/w4oWZts7q7f)]
- **<big>TryUnwrap</big>** : 检查 error, 如果 errnil 则展开,则它返回一个有效值,如果 err 不是 nilUnwrap 使用 err 发生 panic。
- **<big>TryUnwrap</big>** : 检查error, 如果errnil则展开则它返回一个有效值如果err不是nilUnwrap使用err发生panic。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#TryUnwrap)]
[[play](https://go.dev/play/p/acyZVkNZEeW)]
- **<big>TryCatch</big>** : 简单实现的java风格异常处理try-catch-finally
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#TryCatch)]
[[play](https://go.dev/play/p/todo)]
## 如何贡献代码

View File

@@ -3,6 +3,7 @@ package compare
import (
"bytes"
"encoding/json"
"math/big"
"reflect"
"time"
@@ -24,6 +25,13 @@ func compareValue(operator string, left, right any) bool {
case reflect.Struct, reflect.Slice, reflect.Map:
return compareRefValue(operator, left, right, leftType.Kind())
case reflect.Ptr:
if leftVal, ok := left.(*big.Int); ok {
if rightVal, ok := right.(*big.Int); ok {
return compareBigInt(operator, leftVal, rightVal)
}
}
}
return false
@@ -155,169 +163,129 @@ func compareBasicValue(operator string, leftValue, rightValue any) bool {
}
switch leftVal := leftValue.(type) {
case json.Number:
if left, err := leftVal.Float64(); err == nil {
switch rightVal := rightValue.(type) {
case json.Number:
if right, err := rightVal.Float64(); err == nil {
switch operator {
case equal:
if left == right {
return true
}
case lessThan:
if left < right {
return true
}
case greaterThan:
if left > right {
return true
}
case lessOrEqual:
if left <= right {
return true
}
case greaterOrEqual:
if left >= right {
return true
}
}
}
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
right, err := convertor.ToFloat(rightValue)
if err != nil {
return false
}
switch operator {
case equal:
if left == right {
return true
}
case lessThan:
if left < right {
return true
}
case greaterThan:
if left > right {
return true
}
case lessOrEqual:
if left <= right {
return true
}
case greaterOrEqual:
if left >= right {
return true
}
}
}
case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
left, err := convertor.ToBigInt(leftValue)
if err != nil {
return false
}
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
right, err := convertor.ToBigInt(rightValue)
if err != nil {
return false
}
return compareBigInt(operator, left, right)
case float32, float64:
left, err := convertor.ToFloat(leftValue)
if err != nil {
return false
}
switch rightVal := rightValue.(type) {
case json.Number:
if right, err := rightVal.Float64(); err == nil {
switch operator {
case equal:
if left == right {
return true
}
case lessThan:
if left < right {
return true
}
case greaterThan:
if left > right {
return true
}
case lessOrEqual:
if left <= right {
return true
}
case greaterOrEqual:
if left >= right {
return true
}
}
}
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
right, err := convertor.ToFloat(rightValue)
if err != nil {
return false
}
switch operator {
case equal:
if left == right {
return true
}
case lessThan:
if left < right {
return true
}
case greaterThan:
if left > right {
return true
}
case lessOrEqual:
if left <= right {
return true
}
case greaterOrEqual:
if left >= right {
return true
}
}
right, err := convertor.ToFloat(rightValue)
if err != nil {
return false
}
return compareFloats(operator, left, right)
case string:
left := leftVal
switch right := rightValue.(type) {
case string:
switch operator {
case equal:
if left == right {
return true
}
case lessThan:
if left < right {
return true
}
case greaterThan:
if left > right {
return true
}
case lessOrEqual:
if left <= right {
return true
}
case greaterOrEqual:
if left >= right {
return true
}
}
return compareStrings(operator, left, right)
}
case bool:
left := leftVal
switch right := rightValue.(type) {
case bool:
switch operator {
case equal:
if left == right {
return true
}
}
return compareBools(operator, left, right)
}
case json.Number:
if left, err := leftVal.Float64(); err == nil {
switch rightVal := rightValue.(type) {
case json.Number:
if right, err := rightVal.Float64(); err == nil {
return compareFloats(operator, left, right)
}
case float32, float64:
right, err := convertor.ToFloat(rightValue)
if err != nil {
return false
}
return compareFloats(operator, left, right)
case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
right, err := convertor.ToBigInt(rightValue)
if err != nil {
return false
}
left, err := convertor.ToBigInt(left)
return compareBigInt(operator, left, right)
}
}
}
return false
}
// compareBigInt compares two big.Int values based on the operator
func compareBigInt(operator string, left, right *big.Int) bool {
switch operator {
case equal:
return left.Cmp(right) == 0
case lessThan:
return left.Cmp(right) < 0
case greaterThan:
return left.Cmp(right) > 0
case lessOrEqual:
return left.Cmp(right) <= 0
case greaterOrEqual:
return left.Cmp(right) >= 0
}
return false
}
// compareFloats compares two float64 values based on the operator
func compareFloats(operator string, left, right float64) bool {
switch operator {
case equal:
return left == right
case lessThan:
return left < right
case greaterThan:
return left > right
case lessOrEqual:
return left <= right
case greaterOrEqual:
return left >= right
}
return false
}
// compareStrings compares two string values based on the operator
func compareStrings(operator string, left, right string) bool {
switch operator {
case equal:
return left == right
case lessThan:
return left < right
case greaterThan:
return left > right
case lessOrEqual:
return left <= right
case greaterOrEqual:
return left >= right
}
return false
}
// compareBools compares two boolean values based on the operator
func compareBools(operator string, left, right bool) bool {
switch operator {
case equal:
return left == right
}
return false
}

View File

@@ -2,6 +2,7 @@ package compare
import (
"encoding/json"
"math/big"
"testing"
"time"
@@ -12,213 +13,191 @@ func TestEqual(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEqual")
// basic type
assert.Equal(true, Equal(1, 1))
assert.Equal(true, Equal(int64(1), int64(1)))
assert.Equal(true, Equal("a", "a"))
assert.Equal(true, Equal(true, true))
assert.Equal(true, Equal([]int{1, 2, 3}, []int{1, 2, 3}))
assert.Equal(true, Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"}))
assert.Equal(false, Equal(1, 2))
assert.Equal(false, Equal(1, int64(1)))
assert.Equal(false, Equal("a", "b"))
assert.Equal(false, Equal(true, false))
assert.Equal(false, Equal([]int{1, 2}, []int{1, 2, 3}))
assert.Equal(false, Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a"}))
// time
time1 := time.Now()
time2 := time1.Add(time.Second)
time3 := time1.Add(time.Second)
assert.Equal(false, Equal(time1, time2))
assert.Equal(true, Equal(time2, time3))
// struct
st1 := struct {
A string
B string
tests := []struct {
left any
right any
want bool
}{
A: "a",
B: "b",
{1, 1, true},
{int64(1), int64(1), true},
{"a", "a", true},
{true, true, true},
{[]int{1, 2, 3}, []int{1, 2, 3}, true},
{map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"}, true},
{1, 2, false},
{1, int64(1), false},
{"a", "b", false},
{true, false, false},
{[]int{1, 2}, []int{1, 2, 3}, false},
{map[int]string{1: "a", 2: "b"}, map[int]string{1: "a"}, false},
// {time.Now(), time.Now(), true},
// {time.Now(), time.Now().Add(time.Second), false},
{[]byte("hello"), []byte("hello"), true},
{[]byte("hello"), []byte("world"), false},
{json.Number("123"), json.Number("123"), true},
{json.Number("123"), json.Number("124"), false},
{big.NewInt(123), big.NewInt(123), true},
}
st2 := struct {
A string
B string
}{
A: "a",
B: "b",
for _, tt := range tests {
assert.Equal(tt.want, Equal(tt.left, tt.right))
}
st3 := struct {
A string
B string
}{
A: "a1",
B: "b",
}
assert.Equal(true, Equal(st1, st2))
assert.Equal(false, Equal(st1, st3))
//byte slice
bs1 := []byte("hello")
bs2 := []byte("hello")
assert.Equal(true, Equal(bs1, bs2))
// json.Number
var jsonNumber1, jsonNumber2 json.Number
json.Unmarshal([]byte(`123`), &jsonNumber1)
json.Unmarshal([]byte(`123`), &jsonNumber2)
assert.Equal(true, Equal(jsonNumber1, jsonNumber2))
}
func TestEqualValue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEqualValue")
assert.Equal(true, EqualValue(1, 1))
assert.Equal(true, EqualValue(int(1), int64(1)))
assert.Equal(true, EqualValue(1, "1"))
tests := []struct {
left any
right any
want bool
}{
{1, 1, true},
{int64(1), int64(1), true},
{"a", "a", true},
{true, true, true},
{[]int{1, 2, 3}, []int{1, 2, 3}, true},
{map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"}, true},
{1, 2, false},
{1, int64(1), true},
{"a", "b", false},
{true, false, false},
{[]int{1, 2}, []int{1, 2, 3}, false},
}
assert.Equal(false, EqualValue(1, "2"))
// json.Number
var jsonNumber1, jsonNumber2 json.Number
json.Unmarshal([]byte(`123`), &jsonNumber1)
json.Unmarshal([]byte(`123`), &jsonNumber2)
assert.Equal(true, EqualValue(jsonNumber1, 123))
for _, tt := range tests {
assert.Equal(tt.want, EqualValue(tt.left, tt.right))
}
}
func TestLessThan(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLessThan")
assert.Equal(true, LessThan(1, 2))
assert.Equal(true, LessThan(1.1, 2.2))
assert.Equal(true, LessThan("a", "b"))
tests := []struct {
left any
right any
want bool
}{
{1, 2, true},
{1.1, 2.2, true},
{"a", "b", true},
{time.Now(), time.Now().Add(time.Second), true},
{[]byte("hello1"), []byte("hello2"), true},
{json.Number("123"), json.Number("124"), true},
{645680099112988673, 645680099112988675, true},
{1, 1, false},
{1, int64(1), false},
}
time1 := time.Now()
time2 := time1.Add(time.Second)
assert.Equal(true, LessThan(time1, time2))
assert.Equal(false, LessThan(1, 1))
assert.Equal(false, LessThan(1, int64(1)))
bs1 := []byte("hello1")
bs2 := []byte("hello2")
assert.Equal(true, LessThan(bs1, bs2))
// json.Number
var jsonNumber1, jsonNumber2 json.Number
json.Unmarshal([]byte(`123`), &jsonNumber1)
json.Unmarshal([]byte(`124`), &jsonNumber2)
assert.Equal(true, LessThan(jsonNumber1, jsonNumber2))
for _, tt := range tests {
assert.Equal(tt.want, LessThan(tt.left, tt.right))
}
}
func TestGreaterThan(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGreaterThan")
assert.Equal(true, GreaterThan(2, 1))
assert.Equal(true, GreaterThan(2.2, 1.1))
assert.Equal(true, GreaterThan("b", "a"))
tests := []struct {
left any
right any
want bool
}{
{2, 1, true},
{2.2, 1.1, true},
{"b", "a", true},
{time.Now().Add(time.Second), time.Now(), true},
{[]byte("hello2"), []byte("hello1"), true},
{json.Number("124"), json.Number("123"), true},
{645680099112988675, 645680099112988673, true},
{1, 1, false},
{1, int64(1), false},
}
time1 := time.Now()
time2 := time1.Add(time.Second)
assert.Equal(true, GreaterThan(time2, time1))
for _, tt := range tests {
assert.Equal(tt.want, GreaterThan(tt.left, tt.right))
}
assert.Equal(false, GreaterThan(1, 2))
assert.Equal(false, GreaterThan(int64(2), 1))
assert.Equal(false, GreaterThan("b", "c"))
bs1 := []byte("hello1")
bs2 := []byte("hello2")
assert.Equal(true, GreaterThan(bs2, bs1))
// json.Number
var jsonNumber1, jsonNumber2 json.Number
json.Unmarshal([]byte(`123`), &jsonNumber1)
json.Unmarshal([]byte(`124`), &jsonNumber2)
assert.Equal(true, GreaterThan(jsonNumber2, jsonNumber1))
}
func TestLessOrEqual(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLessOrEqual")
assert.Equal(true, LessOrEqual(1, 2))
assert.Equal(true, LessOrEqual(1, 1))
assert.Equal(true, LessOrEqual(1.1, 2.2))
assert.Equal(true, LessOrEqual("a", "b"))
tests := []struct {
left any
right any
want bool
}{
{1, 2, true},
{1, 1, true},
{1.1, 2.2, true},
{"a", "b", true},
{time.Now(), time.Now().Add(time.Second), true},
{[]byte("hello1"), []byte("hello2"), true},
{json.Number("123"), json.Number("124"), true},
{645680099112988673, 645680099112988675, true},
{2, 1, false},
{1, int64(2), false},
}
time1 := time.Now()
time2 := time1.Add(time.Second)
assert.Equal(true, LessOrEqual(time1, time2))
assert.Equal(false, LessOrEqual(2, 1))
assert.Equal(false, LessOrEqual(1, int64(2)))
bs1 := []byte("hello1")
bs2 := []byte("hello2")
assert.Equal(true, LessOrEqual(bs1, bs2))
// json.Number
var jsonNumber1, jsonNumber2 json.Number
json.Unmarshal([]byte(`123`), &jsonNumber1)
json.Unmarshal([]byte(`124`), &jsonNumber2)
assert.Equal(true, LessOrEqual(jsonNumber1, jsonNumber2))
for _, tt := range tests {
assert.Equal(tt.want, LessOrEqual(tt.left, tt.right))
}
}
func TestGreaterOrEqual(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGreaterThan")
assert.Equal(true, GreaterOrEqual(2, 1))
assert.Equal(true, GreaterOrEqual(1, 1))
assert.Equal(true, GreaterOrEqual(2.2, 1.1))
assert.Equal(true, GreaterOrEqual("b", "b"))
tests := []struct {
left any
right any
want bool
}{
{2, 1, true},
{1, 1, true},
{2.2, 1.1, true},
{"b", "b", true},
{time.Now().Add(time.Second), time.Now(), true},
{[]byte("hello2"), []byte("hello1"), true},
{json.Number("124"), json.Number("123"), true},
{645680099112988675, 645680099112988673, true},
{1, 2, false},
{int64(2), 1, false},
{"b", "c", false},
}
time1 := time.Now()
time2 := time1.Add(time.Second)
assert.Equal(true, GreaterOrEqual(time2, time1))
assert.Equal(false, GreaterOrEqual(1, 2))
assert.Equal(false, GreaterOrEqual(int64(2), 1))
assert.Equal(false, GreaterOrEqual("b", "c"))
bs1 := []byte("hello1")
bs2 := []byte("hello2")
assert.Equal(true, GreaterOrEqual(bs2, bs1))
// json.Number
var jsonNumber1, jsonNumber2 json.Number
json.Unmarshal([]byte(`123`), &jsonNumber1)
json.Unmarshal([]byte(`124`), &jsonNumber2)
assert.Equal(true, GreaterOrEqual(jsonNumber2, jsonNumber1))
for _, tt := range tests {
assert.Equal(tt.want, GreaterOrEqual(tt.left, tt.right))
}
}
func TestInDelta(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestInDelta")
assert.Equal(true, InDelta(1, 1, 0))
assert.Equal(false, InDelta(1, 2, 0))
tests := []struct {
left float64
right float64
delta float64
want bool
}{
{1, 1, 0, true},
{1, 2, 0, false},
{2.0 / 3.0, 0.66667, 0.001, true},
{2.0 / 3.0, 0.0, 0.001, false},
{float64(74.96) - float64(20.48), 54.48, 0, false},
{float64(74.96) - float64(20.48), 54.48, 1e-14, true},
{float64(float32(80.45)), float64(80.45), 0, false},
{float64(float32(80.45)), float64(80.45), 1e-5, true},
}
assert.Equal(true, InDelta(2.0/3.0, 0.66667, 0.001))
assert.Equal(false, InDelta(2.0/3.0, 0.0, 0.001))
assert.Equal(false, InDelta(float64(74.96)-float64(20.48), 54.48, 0))
assert.Equal(true, InDelta(float64(74.96)-float64(20.48), 54.48, 1e-14))
assert.Equal(false, InDelta(float64(float32(80.45)), float64(80.45), 0))
assert.Equal(true, InDelta(float64(float32(80.45)), float64(80.45), 1e-5))
for _, tt := range tests {
assert.Equal(tt.want, InDelta(tt.left, tt.right, tt.delta))
}
}

View File

@@ -14,6 +14,7 @@ import (
"fmt"
"io"
"math"
"math/big"
"reflect"
"strconv"
"strings"
@@ -74,7 +75,7 @@ func ToBytes(value any) ([]byte, error) {
// ToChar convert string to char slice.
// Play: https://go.dev/play/p/JJ1SvbFkVdM
func ToChar(s string) []string {
c := make([]string, 0)
c := make([]string, 0, len(s))
if len(s) == 0 {
c = append(c, "")
}
@@ -483,3 +484,36 @@ func ToRawUrlBase64(value any) string {
return base64.RawURLEncoding.EncodeToString(marshal)
}
}
// ToBigInt converts an integer of any supported type (int, int64, uint64, etc.) to *big.Int
// Play: todo
func ToBigInt[T any](v T) (*big.Int, error) {
result := new(big.Int)
switch v := any(v).(type) {
case int:
result.SetInt64(int64(v)) // Convert to int64 for big.Int
case int8:
result.SetInt64(int64(v))
case int16:
result.SetInt64(int64(v))
case int32:
result.SetInt64(int64(v))
case int64:
result.SetInt64(v)
case uint:
result.SetUint64(uint64(v)) // Convert to uint64 for big.Int
case uint8:
result.SetUint64(uint64(v))
case uint16:
result.SetUint64(uint64(v))
case uint32:
result.SetUint64(uint64(v))
case uint64:
result.SetUint64(v)
default:
return nil, fmt.Errorf("unsupported type: %T", v)
}
return result, nil
}

View File

@@ -571,3 +571,12 @@ func ExampleToRawUrlBase64() {
// dHJ1ZQ
// ZXJy
}
func ExampleToBigInt() {
n := 9876543210
bigInt, _ := ToBigInt(n)
fmt.Println(bigInt)
// Output:
// 9876543210
}

View File

@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
"math/big"
"reflect"
"strconv"
"testing"
@@ -741,3 +742,83 @@ func TestToRawUrlBase64(t *testing.T) {
d15, _ := base64.RawURLEncoding.DecodeString(r15)
assert.Equal("4+3/4?=", string(d15))
}
func TestToBigInt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToBigInt")
tests := []struct {
name string
input any
want *big.Int
hasErr bool
}{
{
name: "int",
input: 42,
want: big.NewInt(42),
},
{
name: "int8",
input: int8(127),
want: big.NewInt(127),
},
{
name: "int16",
input: int16(32000),
want: big.NewInt(32000),
},
{
name: "int32",
input: int32(123456),
want: big.NewInt(123456),
},
{
name: "int64",
input: int64(987654321),
want: big.NewInt(987654321),
},
{
name: "uint",
input: uint(987654321),
want: big.NewInt(987654321),
},
{
name: "uint8",
input: uint8(255),
want: big.NewInt(255),
},
{
name: "uint16",
input: uint16(65535),
want: big.NewInt(65535),
},
{
name: "uint32",
input: uint32(4294967295),
want: big.NewInt(4294967295),
},
{
name: "uint64",
input: uint64(18446744073709551615),
want: new(big.Int).SetUint64(18446744073709551615),
},
{
name: "unsupported type",
input: 3.14, // Unsupported type
hasErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ToBigInt(tt.input)
if (err != nil) != tt.hasErr {
t.Errorf("ToBigInt() error = %v, hasErr %v", err, tt.hasErr)
return
}
assert.Equal(tt.want, got)
})
}
}

51
cryptor/rsa_private.pem Normal file
View File

@@ -0,0 +1,51 @@
-----BEGIN rsa private key-----
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
-----END rsa private key-----

View File

@@ -1,51 +1,51 @@
-----BEGIN rsa private key-----
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
-----END rsa private key-----

14
cryptor/rsa_public.pem Normal file
View File

@@ -0,0 +1,14 @@
-----BEGIN rsa public key-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5IqWfYbW1NlTDWE2plFW
qD6CTquA0Ar/1E66lY8OMtrdpxTmchirmoISWN0BD7r2tV9T/kHs44Sy3raAfkR5
ixYF5FRkb63FdIAtoynsxS6MEE26fgWuDAa1xwNt+t/uivnpfJk25htpBNkKGT8i
i0TPPLn1N15hMHenT6PzWVjGjQxWcp4dUA4gXTDuqaeu7Oy7Ku2yP90/ra+cjTV8
DnBJ9enQhAfu1LivJO3FgmXeuC3uqhhM3t9ZbNy7tvJI5PXDCaS8iesBvCp5carT
SXWLpFEgvIhXQIsXtxezKAP3gRd8r5JPQI9FZlxyUcyf+Htkn2A4qyKhFElnP1z9
j0YLFhL/gQMdtNIY7yhSb29PyuCG7noz25swrfxbA7ZVppM0J19JNhlpqmusBKLB
NqN+KMD8EDli7NLX17S9Dj2pQF9I8fVXPEhkdTb67rr7y3OUANKjh0Opnt3JLoj9
u1X7BfCeUSR/qq3E8RFPeyxvP1tc5QVqKBG6UPBo8nLQqdzJhUd8a1YEfXIUbdHL
s2q5WVFu2MDavIp634+fzfcIFRoBtdxf5aCdxLaLocsA/aLLyL1pK6K0rpdrSUtc
EBMST26qIlU0Ht+SQtaMdE2gyjkMM5RpLh1q/gpow+0j3zu6f5tDsu3qwgjLIx78
YCTGUuCpsVMzFK4tahYSPNkCAwEAAQ==
-----END rsa public key-----

View File

@@ -1,14 +1,14 @@
-----BEGIN rsa public key-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA3bRSY5GD7uJB3jvwqa9Z
ZFpN3uLIGbbPA+yiyf6tJZp3K3rmkVFfEcWqtK1EfHvd9G4rqLYJ9ZcohDZgD/Ww
mqJtaaWh2/7feMPaitp50bYVilpPhaxULx+MIjQn3XXowYvr4fX7N052t4IC95tA
anPEEwZRQJOVMtibAxwI/ofUOCpTPtuK3AoErDxS18JPgjQ34yY4Jsch0de53+Sj
Tk+bJpLUlnY4brm+A23FhwTlE5njrKA+Texrg52KJ8aPhLuVQBcZP1SJsxv2PZru
uD+0xfLDRrZ7BOTpun+1FBhdlxBefIfBQbBBfy7STw+ignTaO+IRIHhcqKZ+12Na
+4GAusmpSiB3LATy82h0nB0PX3hSOLYmFI61px4l/yM50E4brF1NFtd/BpoozZaj
gxjJaznuZXFQ1YSG0JjCeszqdzU+6dexGTr+4Lr87NfLekmUX1nZYy/E5lST65lG
lI4hX1nR5+nVN9ALRYByNz6oJd0IfF4dhoNlGPc1VksskeY8rPZwXITbSifAN7zv
EiwKreFV3t0BLKsvWRu9GdpWy+d2AmelXkNm+QaH2mPM17euMoNZVyzizrZaJkh/
aHO/UgY1/y7sXFl4akC9hk9ILONCUn6FVI4BXMXb5kZgwDk5tWE5A159LtC579yG
cnxyc9Y9NNFOGrqFqPiu6QUCAwEAAQ==
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwGdN8KE2NTK41cVN7i6m
ZZS5J86gjNs0LJDHylb2GG+K4O8sfq98EMKMJ2xGnKoVRJXucVohr5Eiuf5zgxQe
9mpYDyDQ0vnpBkoNkfzJNZQvcQFaIllUeH+eN4hSBhMegPspCr2BcmC/m/N40+Pj
BMDaHSzeNE2SyIuyflLC7GhQvHnkcQXkqJVNC1yesV7zYKDV/xYPI0NxN0kE+4eR
650A77jso4gloRUek0cpU4ztpe6Zz4za7AEKHmZO8pVHpQJihbNMhItbo6BcgeOF
WImXyJfcbCtu1ayciaJ0Q45Z1btuF2wFwQjwZGt7DAvbzYwMBBiTpGxig/8kzibm
7bL1Td7huW6Knqbfh4/v+2m+2aNK1u0TfncFUr17wDDfeVj/xeNOSbPu2X/AppjV
X0rxmvWN+AByFfAuw7/kqMK7QZlA+5nNjmOojvryGOSu1he4PUnhRyJ7jofOIrLZ
9YYBXpRiY/WB8t+xWIlaoPXFmsOxSgMwzQFGMlnSFy7nK9T4znE0QFknOQNbELPE
B4UGLOEa5Tg6YD2ORDDSqCzMRdkE1kAgoMRC9DkRXE45KEcQlhMX9Pahwx3mPS4l
MWABVudiEWyhGaR279OWjezqvtoLLBJ5GD9QL1XqaqCaJjp+qsHmX8re+MTA3ZJu
yUtRoPXPsKCe2nZ6Ma87DlUCAwEAAQ==
-----END rsa public key-----

View File

@@ -209,7 +209,7 @@ func (dl *DoublyLink[T]) Size() int {
// Values return slice of all doubly linklist node value
func (dl *DoublyLink[T]) Values() []T {
result := []T{}
result := make([]T, 0, dl.length)
current := dl.Head
for current != nil {
result = append(result, current.Value)

View File

@@ -212,7 +212,7 @@ func (sl *SinglyLink[T]) Size() int {
// Values return slice of all singly linklist node value
func (sl *SinglyLink[T]) Values() []T {
result := []T{}
result := make([]T, 0, sl.length)
current := sl.Head
for current != nil {
result = append(result, current.Value)

View File

@@ -31,7 +31,7 @@ func NewArrayQueue[T any](capacity int) *ArrayQueue[T] {
// Data return slice of queue data
func (q *ArrayQueue[T]) Data() []T {
items := []T{}
items := make([]T, 0, q.tail-q.head)
for i := q.head; i < q.tail; i++ {
items = append(items, q.data[i])
}

View File

@@ -27,7 +27,7 @@ func NewLinkedQueue[T any]() *LinkedQueue[T] {
// Data return slice of queue data
func (q *LinkedQueue[T]) Data() []T {
res := []T{}
res := make([]T, 0, q.length)
current := q.head
for current != nil {

View File

@@ -24,7 +24,7 @@ func NewLinkedStack[T any]() *LinkedStack[T] {
// Data return stack data
func (s *LinkedStack[T]) Data() []T {
res := []T{}
res := make([]T, 0, s.length)
current := s.top
for current != nil {

View File

@@ -100,12 +100,6 @@ func TestBSTree_Delete(t *testing.T) {
acturl1 := bstree.InOrderTraverse()
assert.Equal([]int{2, 5, 6, 7}, acturl1)
//todo
// bstree.DeletetNode(6, comparator)
// bstree.Print()
// acturl2 := bstree.InOrderTraverse()
// assert.Equal([]int{2, 5, 7}, acturl2)
}
func TestBSTree_Depth(t *testing.T) {

View File

@@ -147,7 +147,7 @@ func printTreeNodes[T any](nodes []*datastructure.TreeNode[T], level, maxLevel i
printSpaces(firstSpaces)
newNodes := []*datastructure.TreeNode[T]{}
newNodes := make([]*datastructure.TreeNode[T], 0, len(nodes)*2)
for _, node := range nodes {
if node != nil {
fmt.Printf("%v", node.Value)

View File

@@ -47,6 +47,7 @@ import (
- [ToUrlBase64](#ToUrlBase64)
- [ToRawStdBase64](#ToRawStdBase64)
- [ToRawUrlBase64](#ToRawUrlBase64)
- [ToBigInt](#ToBigInt)
<div STYLE="page-break-after: always;"></div>
@@ -1148,4 +1149,34 @@ func main() {
// dHJ1ZQ
// ZXJy
}
```
### <span id="ToBigInt">ToBigInt</span>
<p>将整数值转换为bigInt。</p>
<b>函数签名:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
```go
func ToBigInt[T any](v T) (*big.Int, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
n := 9876543210
bigInt, _ := convertor.ToBigInt(n)
fmt.Println(bigInt)
// Output:
// 9876543210
}
```

View File

@@ -33,7 +33,7 @@ import (
- [Percent](#Percent)
- [RoundToFloat](#RoundToFloat)
- [RoundToString](#RoundToString)
- [TruncRound](#TruncRound)
- [T运行cRound](#T运行cRound)
- [CeilToFloat](#CeilToFloat)
- [CeilToString](#CeilToString)
- [FloorToFloat](#FloorToFloat)
@@ -52,6 +52,10 @@ import (
- [Sum](#Sum)
- [Abs](#Abs)
- [Div](#Div)
- [Variance](#Variance)
- [StdDev](#StdDev)
- [Permutation](#Permutation)
- [Combination](#Combination)
<div STYLE="page-break-after: always;"></div>
@@ -64,7 +68,7 @@ import (
<b>函数签名:</b>
```go
func Average[T constraints.Integer | constraints.Float](numbers ...T) T
func Average[T constraints.Integer | constraints.Float](numbers ...T) float64
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HFd70x4DrMj)</span></b>
@@ -87,7 +91,7 @@ func main() {
fmt.Println(result2)
// Output:
// 1
// 1.5
// 1.3
}
```
@@ -462,14 +466,14 @@ func main() {
}
```
### <span id="TruncRound">TruncRound</span>
### <span id="T运行cRound">T运行cRound</span>
<p>截短n位小数不进行四舍五入</p>
<b>函数签名:</b>
```go
func TruncRound[T constraints.Float | constraints.Integer](x T, n int) T
func T运行cRound[T constraints.Float | constraints.Integer](x T, n int) T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/aumarSHIGzP)</span></b>
@@ -483,9 +487,9 @@ import (
)
func main() {
result1 := mathutil.TruncRound(0.124, 2)
result2 := mathutil.TruncRound(0.125, 2)
result3 := mathutil.TruncRound(0.125, 3)
result1 := mathutil.T运行cRound(0.124, 2)
result2 := mathutil.T运行cRound(0.125, 2)
result3 := mathutil.T运行cRound(0.125, 3)
fmt.Println(result1)
fmt.Println(result2)
@@ -1045,8 +1049,8 @@ import (
func main() {
result1 := mathutil.Log(8, 2)
result2 := mathutil.TruncRound(mathutil.Log(5, 2), 2)
result3 := mathutil.TruncRound(mathutil.Log(27, 3), 0)
result2 := mathutil.T运行cRound(mathutil.Log(5, 2), 2)
result3 := mathutil.T运行cRound(mathutil.Log(27, 3), 0)
fmt.Println(result1)
fmt.Println(result2)
@@ -1162,4 +1166,136 @@ func main() {
// 0.5
// 0
}
```
### <span id="Variance">Variance</span>
<p>计算方差。</p>
<b>函数签名:</b>
```go
func Variance[T constraints.Float | constraints.Integer](numbers []T) float64
```
<b>示例:<span style="float:right;display:inline-block;">[示例](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Variance([]int{1, 2, 3, 4, 5})
result2 := mathutil.Variance([]float64{1.1, 2.2, 3.3, 4.4, 5.5})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 2
// 2.42
}
```
### <span id="StdDev">StdDev</span>
<p>计算标准差。</p>
<b>函数签名:</b>
```go
func StdDev[T constraints.Float | constraints.Integer](numbers []T) float64
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.T运行cRound(mathutil.StdDev([]int{1, 2, 3, 4, 5}), 2)
result2 := mathutil.T运行cRound(mathutil.StdDev([]float64{1.1, 2.2, 3.3, 4.4, 5.5}), 2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1.41
// 1.55
}
```
### <span id="Permutation">Permutation</span>
<p>计算排列数P(n, k)。</p>
<b>函数签名:</b>
```go
func Permutation(n, k uint) uint
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Permutation(5, 3)
result2 := mathutil.Permutation(5, 5)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 60
// 120
}
```
### <span id="Combination">Combination</span>
<p>计算组合数C(n, k)。</p>
<b>函数签名:</b>
```go
func Combination(n, k uint) uint
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Combination(5, 3)
result2 := mathutil.Combination(5, 5)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 10
// 1
}
```

View File

@@ -526,7 +526,7 @@ func main() {
```
### <span id="RandNumberOfLength">RandNumberOfLength</span>
<p>生成指定长度的随机数</p>
<p>生成指定长度的随机数</p>
<b>函数签名:</b>

View File

@@ -47,6 +47,7 @@ import (
- [ToUrlBase64](#ToUrlBase64)
- [ToRawStdBase64](#ToRawStdBase64)
- [ToRawUrlBase64](#ToRawUrlBase64)
- [ToBigInt](#ToBigInt)
<div STYLE="page-break-after: always;"></div>
@@ -1116,4 +1117,34 @@ func main() {
// map[a:1 b:2] false
// &{test 1 0.1 true <nil> } false
}
```
### <span id="ToBigInt">ToBigInt</span>
<p>Converts an integer of any supported type (int, int64, uint64, etc.) to *big.Int</p>
<b>Signature:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
```go
func ToBigInt[T any](v T) (*big.Int, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
n := 9876543210
bigInt, _ := convertor.ToBigInt(n)
fmt.Println(bigInt)
// Output:
// 9876543210
}
```

View File

@@ -52,6 +52,10 @@ import (
- [Sum](#Sum)
- [Abs](#Abs)
- [Div](#Div)
- [Variance](#Variance)
- [StdDev](#StdDev)
- [Permutation](#Permutation)
- [Combination](#Combination)
<div STYLE="page-break-after: always;"></div>
@@ -64,7 +68,7 @@ import (
<b>Signature:</b>
```go
func Average[T constraints.Integer | constraints.Float](numbers ...T) T
func Average[T constraints.Integer | constraints.Float](numbers ...T) float64
```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/Vv7LBwER-pz)</span></b>
@@ -87,7 +91,7 @@ func main() {
fmt.Println(result2)
// Output:
// 1
// 1.5
// 1.3
}
```
@@ -1161,4 +1165,136 @@ func main() {
// 0.5
// 0
}
```
### <span id="Variance">Variance</span>
<p>Returns the variance of numbers.</p>
<b>Signature:</b>
```go
func Variance[T constraints.Float | constraints.Integer](numbers []T) float64
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Variance([]int{1, 2, 3, 4, 5})
result2 := mathutil.Variance([]float64{1.1, 2.2, 3.3, 4.4, 5.5})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 2
// 2.42
}
```
### <span id="StdDev">StdDev</span>
<p>Returns the standard deviation of numbers.</p>
<b>Signature:</b>
```go
func StdDev[T constraints.Float | constraints.Integer](numbers []T) float64
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.TruncRound(mathutil.StdDev([]int{1, 2, 3, 4, 5}), 2)
result2 := mathutil.TruncRound(mathutil.StdDev([]float64{1.1, 2.2, 3.3, 4.4, 5.5}), 2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1.41
// 1.55
}
```
### <span id="Permutation">Permutation</span>
<p>Calculates P(n, k).</p>
<b>Signature:</b>
```go
func Permutation(n, k uint) uint
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Permutation(5, 3)
result2 := mathutil.Permutation(5, 5)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 60
// 120
}
```
### <span id="Combination">Combination</span>
<p>Calculates C(n, k).</p>
<b>Signature:</b>
```go
func Combination(n, k uint) uint
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Combination(5, 3)
result2 := mathutil.Combination(5, 5)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 10
// 1
}
```

View File

@@ -10,7 +10,7 @@ outline: deep
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
```
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.4. </b>
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.5. </b>
```go
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x

View File

@@ -2,7 +2,7 @@
### Sponsor me
<b>Hello, I am a software developer and have been engaged in development work for 13 years. Love open source software. And be willing to put in the energy for it. I am the creator of project [lancet](https://github.com/duke-git/lancet). Since Lancet was released as open source two years ago, it has been used by more than 1,000 internal and external projects. lancet will always be free for all users. Your support is a powerful encouragement for me to continue my struggle. Thanks! You can use WeChat to scans the following QR code or clicks the following sponsor button to initiate sponsorship.</b>
<b>Hello, I am a software developer and have been engaged in development work for 15 years. Love open source software. And be willing to put in the energy for it. I am the creator of project [lancet](https://github.com/duke-git/lancet). Since Lancet was released as open source in 2021, it has been used by more than 1700 internal and external projects. lancet will always be free for all users. Your support is a powerful encouragement for me to continue my struggle. Thanks! You can use WeChat to scans the following QR code or clicks the following sponsor button to initiate sponsorship.</b>
<style>
.sponsor-ctn {

View File

@@ -10,7 +10,7 @@ outline: deep
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
```
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.4。</b>
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.5。</b>
```go
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x

View File

@@ -1,6 +1,6 @@
### 赞助
<b>您好,我是一名软件开发者,从事开发工作 13 年。热爱软件开源。并愿意为此付出精力。是开源项目[lancet](https://github.com/duke-git/lancet)的作者。Lancet 自两年前开源发布以来,已有超过 1000 个内外部项目使用。lancet 一直会对所有用户免费。您的支持是对我继续奋斗的有力鼓励。谢谢! 微信扫描以下二维码或点击以下赞助按钮发起赞助。 </b>
<b>您好,我是一名软件开发者,从事开发工作15年。热爱软件开源。并愿意为此付出精力。是开源项目[lancet](https://github.com/duke-git/lancet)的作者。Lancet自2021年前开源发布以来,已有超过1700个内外部项目使用。lancet一直会对所有用户免费。您的支持是对我继续奋斗的有力鼓励。谢谢! 微信扫描以下二维码或点击以下赞助按钮发起赞助。 </b>
<style>
.sponsor-ctn {

View File

@@ -14,7 +14,6 @@ import (
"encoding/csv"
"errors"
"fmt"
"github.com/duke-git/lancet/v2/validator"
"io"
"io/fs"
"net/http"
@@ -24,6 +23,8 @@ import (
"sort"
"strings"
"sync"
"github.com/duke-git/lancet/v2/validator"
)
// FileReader is a reader supporting offset seeking and reading one
@@ -819,6 +820,7 @@ func WriteMapsToCsv(filepath string, records []map[string]any, appendToExistingF
if len(headers) > 0 {
columnHeaders = headers[0]
} else {
columnHeaders = make([]string, 0, len(records[0]))
for key := range records[0] {
columnHeaders = append(columnHeaders, key)
}
@@ -832,7 +834,7 @@ func WriteMapsToCsv(filepath string, records []map[string]any, appendToExistingF
}
for _, record := range records {
var row []string
row := make([]string, 0, len(columnHeaders))
for _, h := range columnHeaders {
row = append(row, fmt.Sprintf("%v", record[h]))
}

View File

@@ -44,14 +44,19 @@ func Fibonacci(first, second, n int) int {
}
}
// Factorial calculate x!.
// Factorial calculate n!.
// Play: https://go.dev/play/p/tt6LdOK67Nx
func Factorial(x uint) uint {
var f uint = 1
for ; x > 1; x-- {
f *= x
func Factorial(n uint) uint {
if n == 0 || n == 1 {
return 1
}
return f
result := uint(1)
for i := uint(2); i <= n; i++ {
result *= i
}
return result
}
// Percent calculate the percentage of value to total.
@@ -224,14 +229,12 @@ func Sum[T constraints.Integer | constraints.Float](numbers ...T) T {
// Average return average value of numbers.
// Play: https://go.dev/play/p/Vv7LBwER-pz
func Average[T constraints.Integer | constraints.Float](numbers ...T) T {
var sum T
n := T(len(numbers))
for _, v := range numbers {
sum += v
func Average[T constraints.Integer | constraints.Float](numbers ...T) float64 {
var sum float64
for _, num := range numbers {
sum += float64(num)
}
return sum / n
return sum / float64(len(numbers))
}
// Range creates a slice of numbers from start with specified count, element step is 1.
@@ -395,3 +398,54 @@ func Abs[T constraints.Integer | constraints.Float](x T) T {
func Div[T constraints.Float | constraints.Integer](x T, y T) float64 {
return float64(x) / float64(y)
}
// Variance returns the variance of numbers.
// Play: todo
func Variance[T constraints.Float | constraints.Integer](numbers []T) float64 {
n := len(numbers)
if n == 0 {
return 0
}
avg := Average(numbers...)
var sum float64
for _, v := range numbers {
sum += (float64(v) - avg) * (float64(v) - avg)
}
return sum / float64(n)
}
// StdDev returns the standard deviation of numbers.
// Play: todo
func StdDev[T constraints.Float | constraints.Integer](numbers []T) float64 {
return math.Sqrt(Variance(numbers))
}
// Permutation calculate P(n, k).
// Play: todo
func Permutation(n, k uint) uint {
if n < k {
return 0
}
nFactorial := Factorial(n)
nMinusKFactorial := Factorial(n - k)
return nFactorial / nMinusKFactorial
}
// Combination calculate C(n, k).
// Play: todo
func Combination(n, k uint) uint {
if n < k {
return 0
}
nFactorial := Factorial(n)
kFactorial := Factorial(k)
nMinusKFactorial := Factorial(n - k)
return nFactorial / (kFactorial * nMinusKFactorial)
}

View File

@@ -178,7 +178,7 @@ func ExampleAverage() {
fmt.Println(result2)
// Output:
// 1
// 1.5
// 1.3
}
@@ -478,3 +478,51 @@ func ExampleDiv() {
// 0.5
// 0
}
func ExampleVariance() {
result1 := Variance([]int{1, 2, 3, 4, 5})
result2 := Variance([]float64{1.1, 2.2, 3.3, 4.4, 5.5})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 2
// 2.42
}
func ExampleStdDev() {
result1 := TruncRound(StdDev([]int{1, 2, 3, 4, 5}), 2)
result2 := TruncRound(StdDev([]float64{1.1, 2.2, 3.3, 4.4, 5.5}), 2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1.41
// 1.55
}
func ExamplePermutation() {
result1 := Permutation(5, 3)
result2 := Permutation(5, 5)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 60
// 120
}
func ExampleCombination() {
result1 := Combination(5, 3)
result2 := Combination(5, 5)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 10
// 1
}

View File

@@ -143,11 +143,22 @@ func TestAverage(t *testing.T) {
assert := internal.NewAssert(t, "TestAverage")
assert.Equal(0, Average(0, 0))
assert.Equal(1, Average(1, 1))
tests := []struct {
numbers []int
expected float64
}{
{[]int{0}, 0},
{[]int{1, 1, 1}, 1},
{[]int{1, 2, 3, 4}, 2.5},
{[]int{1, 2, 3, 4, 5}, 3},
}
avg := Average(1.2, 1.4)
assert.Equal(1.3, RoundToFloat(avg, 1))
for _, tt := range tests {
assert.Equal(tt.expected, Average(tt.numbers...))
}
avg := Average(1.1, 1.2, 1.3, 1.4)
assert.Equal(1.25, avg)
}
func TestSum(t *testing.T) {
@@ -413,3 +424,116 @@ func TestDiv(t *testing.T) {
assert.Equal(math.Inf(-1), Div(-8, 0))
assert.Equal(true, math.IsNaN(Div(0, 0)))
}
func TestVariance(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestVariance")
testIntNumbers := []struct {
numbers []int
expected float64
}{
{[]int{0}, 0},
{[]int{1, 1, 1}, 0},
{[]int{1, 2, 3, 4}, 1.25},
{[]int{1, 2, 3, 4, 5}, 2.0},
}
for _, tt := range testIntNumbers {
assert.Equal(tt.expected, TruncRound(Variance(tt.numbers), 2))
}
testFloatNumbers := []struct {
numbers []float64
expected float64
}{
{[]float64{0}, 0},
{[]float64{1, 1, 1}, 0},
{[]float64{1.1, 2.2, 3.3, 4.4}, 1.51},
}
for _, tt := range testFloatNumbers {
assert.Equal(tt.expected, TruncRound(Variance(tt.numbers), 2))
}
}
func TestStdDev(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestStdDev")
testIntNumbers := []struct {
numbers []int
expected float64
}{
{[]int{0}, 0},
{[]int{1, 1, 1}, 0},
{[]int{1, 2, 3, 4}, 1.118},
{[]int{1, 2, 3, 4, 5}, 1.414},
}
for _, tt := range testIntNumbers {
assert.Equal(tt.expected, TruncRound(StdDev(tt.numbers), 3))
}
testFloatNumbers := []struct {
numbers []float64
expected float64
}{
{[]float64{0}, 0},
{[]float64{1, 1, 1}, 0},
{[]float64{1.1, 2.2, 3.3, 4.4}, 1.229},
}
for _, tt := range testFloatNumbers {
assert.Equal(tt.expected, TruncRound(StdDev(tt.numbers), 3))
}
}
func TestPermutation(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPermutation")
tests := []struct {
n uint
k uint
expected uint
}{
{1, 1, 1},
{1, 0, 1},
{0, 1, 0},
{0, 0, 1},
{3, 2, 6},
{4, 2, 12},
}
for _, tt := range tests {
assert.Equal(tt.expected, Permutation(tt.n, tt.k))
}
}
func TestCombination(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCombination")
tests := []struct {
n uint
k uint
expected uint
}{
{1, 1, 1},
{1, 0, 1},
{0, 1, 0},
{0, 0, 1},
{3, 2, 3},
{4, 2, 6},
}
for _, tt := range tests {
assert.Equal(tt.expected, Combination(tt.n, tt.k))
}
}

View File

@@ -71,7 +71,7 @@ func ConvertMapToQueryString(param map[string]any) string {
if param == nil {
return ""
}
var keys []string
keys := make([]string, 0, len(param))
for key := range param {
keys = append(keys, key)
}

View File

@@ -10,6 +10,7 @@ import (
"io"
"math"
"math/rand"
"os"
"time"
"unsafe"
@@ -17,7 +18,7 @@ import (
)
const (
MaximumCapacity = math.MaxInt>>1 + 1
MaximumCapacity = math.MaxInt32>>1 + 1
Numeral = "0123456789"
LowwerLetters = "abcdefghijklmnopqrstuvwxyz"
UpperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -274,7 +275,9 @@ func nearestPowerOfTwo(cap int) int {
// random generate a random string based on given string range.
func random(s string, length int) string {
// 确保随机数生成器的种子是动态的
rand.Seed(time.Now().UnixNano())
pid := os.Getpid()
timestamp := time.Now().UnixNano()
rand.Seed(int64(pid) + timestamp)
// 仿照strings.Builder
// 创建一个长度为 length 的字节切片

View File

@@ -921,36 +921,25 @@ func Merge[T any](slices ...[]T) []T {
// Intersection creates a slice of unique elements that included by all slices.
// Play: https://go.dev/play/p/anJXfB5wq_t
func Intersection[T comparable](slices ...[]T) []T {
if len(slices) == 0 {
return []T{}
}
if len(slices) == 1 {
return Unique(slices[0])
}
result := []T{}
elementCount := make(map[T]int)
reducer := func(sliceA, sliceB []T) []T {
hashMap := make(map[T]int)
for _, v := range sliceA {
hashMap[v] = 1
}
for _, slice := range slices {
seen := make(map[T]bool)
out := make([]T, 0)
for _, val := range sliceB {
if v, ok := hashMap[val]; v == 1 && ok {
out = append(out, val)
hashMap[val]++
for _, item := range slice {
if !seen[item] {
seen[item] = true
elementCount[item]++
}
}
return out
}
result := reducer(slices[0], slices[1])
reduceSlice := make([][]T, 2)
for i := 2; i < len(slices); i++ {
reduceSlice[0] = result
reduceSlice[1] = slices[i]
result = reducer(reduceSlice[0], reduceSlice[1])
for _, item := range slices[0] {
if elementCount[item] == len(slices) {
result = append(result, item)
elementCount[item] = 0
}
}
return result

View File

@@ -202,6 +202,7 @@ func (s Stream[T]) Skip(n int) Stream[T] {
return FromSlice(source)
}
source = make([]T, 0, l-n)
for i := n; i < l; i++ {
source = append(source, s.source[i])
}

View File

@@ -88,8 +88,8 @@ func (s *Struct) ToMap() (map[string]any, error) {
// Fields returns all the struct fields within a slice
func (s *Struct) Fields() []*Field {
var fields []*Field
fieldNum := s.rvalue.NumField()
fields := make([]*Field, 0, fieldNum)
for i := 0; i < fieldNum; i++ {
v := s.rvalue.Field(i)
sf := s.rtype.Field(i)

View File

@@ -34,7 +34,7 @@ func Wrap(cause error, message ...any) *XError {
err := newXError()
if len(message) > 0 {
var newMsgs []string
newMsgs := make([]string, 0, len(message))
for _, m := range message {
newMsgs = append(newMsgs, fmt.Sprintf("%v", m))
}