mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-13 01:02:28 +08:00
Compare commits
7 Commits
v2.3.7
...
385e64cc52
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
385e64cc52 | ||
|
|
be45a259db | ||
|
|
6f703fe577 | ||
|
|
cb8d93c499 | ||
|
|
ae1014c572 | ||
|
|
d5b9e67330 | ||
|
|
a81403766f |
@@ -228,6 +228,42 @@ func ToPointer[T any](value T) *T {
|
|||||||
return &value
|
return &value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToPointers convert a slice of values to a slice of pointers.
|
||||||
|
// Play: todo
|
||||||
|
func ToPointers[T any](values []T) []*T {
|
||||||
|
result := make([]*T, len(values))
|
||||||
|
for i := range values {
|
||||||
|
result[i] = &values[i]
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromPointer returns the value pointed to by the pointer.
|
||||||
|
// Play: todo
|
||||||
|
func FromPointer[T any](ptr *T) T {
|
||||||
|
if ptr == nil {
|
||||||
|
var zeroValue T
|
||||||
|
return zeroValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return *ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromPointers convert a slice of pointers to a slice of values.
|
||||||
|
// Play: todo
|
||||||
|
func FromPointers[T any](pointers []*T) []T {
|
||||||
|
result := make([]T, len(pointers))
|
||||||
|
for i, ptr := range pointers {
|
||||||
|
if ptr == nil {
|
||||||
|
var zeroValue T
|
||||||
|
result[i] = zeroValue
|
||||||
|
} else {
|
||||||
|
result[i] = *ptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// ToMap convert a slice of structs to a map based on iteratee function.
|
// ToMap convert a slice of structs to a map based on iteratee function.
|
||||||
// Play: https://go.dev/play/p/tVFy7E-t24l
|
// Play: https://go.dev/play/p/tVFy7E-t24l
|
||||||
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V {
|
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V {
|
||||||
@@ -406,15 +442,15 @@ func ToStdBase64(value any) string {
|
|||||||
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
switch value.(type) {
|
switch v := value.(type) {
|
||||||
case []byte:
|
case []byte:
|
||||||
return base64.StdEncoding.EncodeToString(value.([]byte))
|
return base64.StdEncoding.EncodeToString(v)
|
||||||
case string:
|
case string:
|
||||||
return base64.StdEncoding.EncodeToString([]byte(value.(string)))
|
return base64.StdEncoding.EncodeToString([]byte(v))
|
||||||
case error:
|
case error:
|
||||||
return base64.StdEncoding.EncodeToString([]byte(value.(error).Error()))
|
return base64.StdEncoding.EncodeToString([]byte(v.Error()))
|
||||||
default:
|
default:
|
||||||
marshal, err := json.Marshal(value)
|
marshal, err := json.Marshal(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -428,15 +464,15 @@ func ToUrlBase64(value any) string {
|
|||||||
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
switch value.(type) {
|
switch v := value.(type) {
|
||||||
case []byte:
|
case []byte:
|
||||||
return base64.URLEncoding.EncodeToString(value.([]byte))
|
return base64.URLEncoding.EncodeToString(v)
|
||||||
case string:
|
case string:
|
||||||
return base64.URLEncoding.EncodeToString([]byte(value.(string)))
|
return base64.URLEncoding.EncodeToString([]byte(v))
|
||||||
case error:
|
case error:
|
||||||
return base64.URLEncoding.EncodeToString([]byte(value.(error).Error()))
|
return base64.URLEncoding.EncodeToString([]byte(v.Error()))
|
||||||
default:
|
default:
|
||||||
marshal, err := json.Marshal(value)
|
marshal, err := json.Marshal(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -450,7 +486,7 @@ func ToRawStdBase64(value any) string {
|
|||||||
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
switch value.(type) {
|
switch v := value.(type) {
|
||||||
case []byte:
|
case []byte:
|
||||||
return base64.RawStdEncoding.EncodeToString(value.([]byte))
|
return base64.RawStdEncoding.EncodeToString(value.([]byte))
|
||||||
case string:
|
case string:
|
||||||
@@ -458,7 +494,7 @@ func ToRawStdBase64(value any) string {
|
|||||||
case error:
|
case error:
|
||||||
return base64.RawStdEncoding.EncodeToString([]byte(value.(error).Error()))
|
return base64.RawStdEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||||
default:
|
default:
|
||||||
marshal, err := json.Marshal(value)
|
marshal, err := json.Marshal(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -472,7 +508,7 @@ func ToRawUrlBase64(value any) string {
|
|||||||
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
switch value.(type) {
|
switch v := value.(type) {
|
||||||
case []byte:
|
case []byte:
|
||||||
return base64.RawURLEncoding.EncodeToString(value.([]byte))
|
return base64.RawURLEncoding.EncodeToString(value.([]byte))
|
||||||
case string:
|
case string:
|
||||||
@@ -480,7 +516,7 @@ func ToRawUrlBase64(value any) string {
|
|||||||
case error:
|
case error:
|
||||||
return base64.RawURLEncoding.EncodeToString([]byte(value.(error).Error()))
|
return base64.RawURLEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||||
default:
|
default:
|
||||||
marshal, err := json.Marshal(value)
|
marshal, err := json.Marshal(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -302,6 +302,75 @@ func TestToPointer(t *testing.T) {
|
|||||||
assert.Equal(*result, 123)
|
assert.Equal(*result, 123)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestToPointers(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestToPointers")
|
||||||
|
|
||||||
|
intVals := []int{1, 2, 3}
|
||||||
|
result := ToPointers(intVals)
|
||||||
|
|
||||||
|
assert.Equal(3, len(result))
|
||||||
|
assert.Equal(1, *result[0])
|
||||||
|
assert.Equal(2, *result[1])
|
||||||
|
assert.Equal(3, *result[2])
|
||||||
|
|
||||||
|
stringVals := []string{"a", "b", "c"}
|
||||||
|
resultStr := ToPointers(stringVals)
|
||||||
|
assert.Equal(3, len(resultStr))
|
||||||
|
assert.Equal("a", *resultStr[0])
|
||||||
|
assert.Equal("b", *resultStr[1])
|
||||||
|
assert.Equal("c", *resultStr[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFromPointer(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestFromPointer")
|
||||||
|
|
||||||
|
intVal := 123
|
||||||
|
pointer := &intVal
|
||||||
|
result := FromPointer(pointer)
|
||||||
|
|
||||||
|
assert.Equal(123, result)
|
||||||
|
|
||||||
|
stringVal := "abc"
|
||||||
|
stringPointer := &stringVal
|
||||||
|
resultStr := FromPointer(stringPointer)
|
||||||
|
|
||||||
|
assert.Equal("abc", resultStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFromPointers(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestFromPointers")
|
||||||
|
|
||||||
|
intPointers := []*int{new(int), new(int), new(int)}
|
||||||
|
*intPointers[0] = 1
|
||||||
|
*intPointers[1] = 2
|
||||||
|
*intPointers[2] = 3
|
||||||
|
|
||||||
|
result := FromPointers(intPointers)
|
||||||
|
|
||||||
|
assert.Equal(3, len(result))
|
||||||
|
assert.Equal(1, result[0])
|
||||||
|
assert.Equal(2, result[1])
|
||||||
|
assert.Equal(3, result[2])
|
||||||
|
|
||||||
|
stringPointers := []*string{new(string), new(string), new(string)}
|
||||||
|
*stringPointers[0] = "a"
|
||||||
|
*stringPointers[1] = "b"
|
||||||
|
*stringPointers[2] = "c"
|
||||||
|
|
||||||
|
resultStr := FromPointers(stringPointers)
|
||||||
|
|
||||||
|
assert.Equal(3, len(resultStr))
|
||||||
|
assert.Equal("a", resultStr[0])
|
||||||
|
assert.Equal("b", resultStr[1])
|
||||||
|
assert.Equal("c", resultStr[2])
|
||||||
|
}
|
||||||
|
|
||||||
func TestEncodeByte(t *testing.T) {
|
func TestEncodeByte(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
@@ -1,51 +1,51 @@
|
|||||||
-----BEGIN rsa private key-----
|
-----BEGIN rsa private key-----
|
||||||
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
|
||||||
-----END rsa private key-----
|
-----END rsa private key-----
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
-----BEGIN rsa public key-----
|
-----BEGIN rsa public key-----
|
||||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw0anfgtraA2uaZwoLpLB
|
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA8O2hLVt/7v6rQF2eGX3J
|
||||||
vo1EkfYvDBgeXoMQ4WMKbcw6jU8k18E+f3WM52I2RssEk6g0X1vIiarHZU5qyxbv
|
+QyteV45lI/5qlyqTe7CiwUg1bkJ2yLHaoGSWoVtthE/X7GZgsw57VEgnazZAehe
|
||||||
2iNoT7EfgizzlXYvx06pM69GNBQrV46+lNhiOv4eeLZcOHBnxAyizlIKyLuwO+C1
|
XcxV8OJWBGuRfmXabtKIzSBF8uZj+H3iPDvJB7NggMh8teYsdBSn9Cm/L5FesDvg
|
||||||
cX/6BxuXjX3ogw+6IaBFZN/EOMmTWc6sPKrnNCEqgCNiTbPAXb+N8j5Iv8QPs0Aw
|
/KxUKKfBU4LSrhOMhBauIoOSVU659y3kYgpzC/ormvCsJSe3KSdIhtLxiv+dnEHh
|
||||||
VTB3jC9LP0mRt2GGD0cu+QIZkoGEhyW9Dd+0tgeIK32uXCF8uDjNpUV1TxCdn5H+
|
9WvsXWB50lIw3TIC041aL5mwRvb5/JWcjtn5bgLEChrnEGF0RYUDMwm8hT1YsEN9
|
||||||
lvgddxfiaIJAdY5UaTx48XRIdULhQrVKXJNyTYWTXbezViYIf1nXOdDI2hsGgKTf
|
Rb9fOx5ZTUZNRVHYjaCyUA+cG+gC72EjrkXY4If3pAESNcF+5NGGJaETd8rHzHsR
|
||||||
NVCocDT1LcT5zebijFHVCWfAAKEPRLdzPZomkFIa3rQQgChgePzE8Oqsaxuwx8sU
|
FRVPXkwhRmkx9nBF+RjQhouqBTptIcIO2rPlTC9H5Oeg+jVljlBJ7/ESeOlg2OEb
|
||||||
09NAo3giSq1OmBBwly7h60Lwtm8+XuwmWtEgZoSQy2Hm8UMAJ3guotfYuS8mPQBi
|
YyOUJpAPMPcz5HiNSTRHuDWIDUuk48BOF9Vo00PJq/oXRzUa9HHhu6cosfZH4P4P
|
||||||
55JZpdqVN0D5SdwuWXhHpO4xDodNYAoMMei1NNgrX2zN3FCS8PVi97wD6cQ8xsWM
|
kDthxq89migqUL+C8WqeZ8I+xFS8/1TpvjOnOYF5ADvByC69UGPEoh+o+ZpgWfAs
|
||||||
62nByrzIjmPwTfoCb3qP/928FMJMg7b3bYBrUnOrpVWZfAIDs4H7DoP8VLL4rMgB
|
Crb9Qwy9WAAZg0rsouoPqb4Qk6Vr88X6I20Ys9AayLzZ72ddoS5IweOoF5/xLfii
|
||||||
5PuWNQ13gtX7y5ZOyLhopiKLnar9XiN8GAMANBdKRI2anGEozrfJoelJ5POXZwSa
|
cGLKckNwG6sy4f1LCFB2Xc79nYqJzlwPGC3pKfEIAXUj1I/p+/MqaTDJQs72dhr0
|
||||||
tRjbL+nWO3YnBzEunCw1xmMCAwEAAQ==
|
lTX5505XUBqrbX0BPGcZvIsCAwEAAQ==
|
||||||
-----END rsa public key-----
|
-----END rsa public key-----
|
||||||
|
|||||||
@@ -620,7 +620,7 @@ func main() {
|
|||||||
|
|
||||||
### <span id="Nand">Nand</span>
|
### <span id="Nand">Nand</span>
|
||||||
|
|
||||||
<p>Returns a composed predicate that represents the logical NAND of a list of predicates. It evaluates to true only if all predicates evaluate to false for the given value.</p>
|
<p>Returns a composed predicate that represents the logical NAND of a list of predicates. It evaluates to false only if all predicates evaluate to true for the given value.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
@@ -650,7 +650,7 @@ func main() {
|
|||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// false
|
// false
|
||||||
// false
|
// true
|
||||||
// true
|
// true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func And[T any](predicates ...func(T) bool) func(T) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Nand returns a composed predicate that represents the logical NAND of a list of predicates.
|
// Nand returns a composed predicate that represents the logical NAND of a list of predicates.
|
||||||
// It evaluates to true only if all predicates evaluate to false for the given value.
|
// It evaluates to false only if all predicates evaluate to true for the given value.
|
||||||
// Play: https://go.dev/play/p/Rb-FdNGpgSO
|
// Play: https://go.dev/play/p/Rb-FdNGpgSO
|
||||||
func Nand[T any](predicates ...func(T) bool) func(T) bool {
|
func Nand[T any](predicates ...func(T) bool) func(T) bool {
|
||||||
if len(predicates) < 2 {
|
if len(predicates) < 2 {
|
||||||
@@ -26,11 +26,11 @@ func Nand[T any](predicates ...func(T) bool) func(T) bool {
|
|||||||
}
|
}
|
||||||
return func(value T) bool {
|
return func(value T) bool {
|
||||||
for _, predicate := range predicates {
|
for _, predicate := range predicates {
|
||||||
if predicate(value) {
|
if !predicate(value) {
|
||||||
return false // Short-circuit on the first true predicate
|
return true // Short-circuit on the first false predicate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true // True if all predicates are false
|
return false // False if all predicates are true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ func ExampleNand() {
|
|||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// false
|
// false
|
||||||
// false
|
// true
|
||||||
// true
|
// true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ func TestPredicatesNandPure(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert.ShouldBeFalse(isNumericAndLength5("12345"))
|
assert.ShouldBeFalse(isNumericAndLength5("12345"))
|
||||||
assert.ShouldBeFalse(isNumericAndLength5("1234"))
|
assert.ShouldBeTrue(isNumericAndLength5("1234"))
|
||||||
assert.ShouldBeTrue(isNumericAndLength5("abcdef"))
|
assert.ShouldBeTrue(isNumericAndLength5("abcdef"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -507,19 +507,17 @@ func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ForEach iterates over elements of slice and invokes function for each element.
|
// ForEach iterates over elements of slice and invokes function for each element.
|
||||||
// Play: https://go.dev/play/p/DrPaa4YsHRF
|
|
||||||
func ForEach[T any](slice []T, iteratee func(index int, item T)) {
|
func ForEach[T any](slice []T, iteratee func(index int, item T)) {
|
||||||
for i := 0; i < len(slice); i++ {
|
for idx, elem := range slice {
|
||||||
iteratee(i, slice[i])
|
iteratee(idx, elem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForEachWithBreak iterates over elements of slice and invokes function for each element,
|
// ForEachWithBreak iterates over elements of slice and invokes function for each element,
|
||||||
// when iteratee return false, will break the for each loop.
|
// when function return false, will break the for each loop.
|
||||||
// Play: https://go.dev/play/p/qScs39f3D9W
|
|
||||||
func ForEachWithBreak[T any](slice []T, iteratee func(index int, item T) bool) {
|
func ForEachWithBreak[T any](slice []T, iteratee func(index int, item T) bool) {
|
||||||
for i := 0; i < len(slice); i++ {
|
for idx, elem := range slice {
|
||||||
if !iteratee(i, slice[i]) {
|
if !iteratee(idx, elem) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1465,36 +1463,28 @@ func Random[T any](slice []T) (val T, idx int) {
|
|||||||
return slice[idx], idx
|
return slice[idx], idx
|
||||||
}
|
}
|
||||||
|
|
||||||
// RightPadding adds padding to the right end of a slice.
|
// RightPadding returns a copy of the slice padding the given value to the right end of a slice.
|
||||||
|
// If paddingLength is zero or less, the function returns a copy of the slice.
|
||||||
// Play: https://go.dev/play/p/0_2rlLEMBXL
|
// Play: https://go.dev/play/p/0_2rlLEMBXL
|
||||||
func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T {
|
func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T {
|
||||||
if paddingLength == 0 {
|
suffix := []T{}
|
||||||
return slice
|
if paddingLength > 0 {
|
||||||
|
suffix = repeat([]T{paddingValue}, paddingLength)
|
||||||
}
|
}
|
||||||
for i := 0; i < paddingLength; i++ {
|
padded := concat(slice, suffix)
|
||||||
slice = append(slice, paddingValue)
|
return padded
|
||||||
}
|
|
||||||
return slice
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LeftPadding adds padding to the left begin of a slice.
|
// LeftPadding returns a copy of the slice padding the given value to the left begin of a slice.
|
||||||
|
// If paddingLength is zero or less, the function returns a copy of the slice.
|
||||||
// Play: https://go.dev/play/p/jlQVoelLl2k
|
// Play: https://go.dev/play/p/jlQVoelLl2k
|
||||||
func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T {
|
func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T {
|
||||||
if paddingLength == 0 {
|
prefix := []T{}
|
||||||
return slice
|
if paddingLength > 0 {
|
||||||
|
prefix = repeat([]T{paddingValue}, paddingLength)
|
||||||
}
|
}
|
||||||
|
padded := concat(prefix, slice)
|
||||||
paddedSlice := make([]T, len(slice)+paddingLength)
|
return padded
|
||||||
i := 0
|
|
||||||
for ; i < paddingLength; i++ {
|
|
||||||
paddedSlice[i] = paddingValue
|
|
||||||
}
|
|
||||||
for j := 0; j < len(slice); j++ {
|
|
||||||
paddedSlice[i] = slice[j]
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
return paddedSlice
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Frequency counts the frequency of each element in the slice.
|
// Frequency counts the frequency of each element in the slice.
|
||||||
|
|||||||
@@ -831,7 +831,7 @@ func ExampleUniqueByComparator() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
caseInsensitiveStrings := UniqueByComparator([]string{"apple", "banana", "Apple", "cherry", "Banana", "date"}, func(item string, other string) bool {
|
caseInsensitiveStrings := UniqueByComparator([]string{"apple", "banana", "Apple", "cherry", "Banana", "date"}, func(item string, other string) bool {
|
||||||
return strings.ToLower(item) == strings.ToLower(other)
|
return strings.EqualFold(item, other)
|
||||||
})
|
})
|
||||||
|
|
||||||
fmt.Println(uniqueNums)
|
fmt.Println(uniqueNums)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package slice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/bits"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"golang.org/x/exp/constraints"
|
"golang.org/x/exp/constraints"
|
||||||
@@ -96,3 +97,71 @@ func partitionAnySlice[T any](slice []T, lowIndex, highIndex int, less func(a, b
|
|||||||
func swap[T any](slice []T, i, j int) {
|
func swap[T any](slice []T, i, j int) {
|
||||||
slice[i], slice[j] = slice[j], slice[i]
|
slice[i], slice[j] = slice[j], slice[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `repeat` returns a new slice that repeats the provided slice the given number of
|
||||||
|
// times. The result has length and capacity (len(x) * count). The result is never nil.
|
||||||
|
// Repeat panics if count is negative or if the result of (len(x) * count) overflows.
|
||||||
|
//
|
||||||
|
// repeat has been provided in the standard lib within the package `slices` under the
|
||||||
|
// name Repeat since GO version 1.21 onwards. As lancet commits to compatibility with GO
|
||||||
|
// 1.18 onwards, we implement the functionality as an internal function.
|
||||||
|
func repeat[S ~[]E, E any](x S, count int) S {
|
||||||
|
if count < 0 {
|
||||||
|
panic("count cannot be negative")
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxInt = ^uint(0) >> 1
|
||||||
|
hi, lo := bits.Mul(uint(len(x)), uint(count))
|
||||||
|
if hi > 0 || lo > maxInt {
|
||||||
|
panic("the result of (len(x) * count) overflows")
|
||||||
|
}
|
||||||
|
|
||||||
|
newslice := make(S, int(lo)) // lo = len(x) * count
|
||||||
|
n := copy(newslice, x)
|
||||||
|
for n < len(newslice) {
|
||||||
|
n += copy(newslice[n:], newslice[:n])
|
||||||
|
}
|
||||||
|
return newslice
|
||||||
|
}
|
||||||
|
|
||||||
|
// concat returns a new slice concatenating the passed in slices.
|
||||||
|
//
|
||||||
|
// concat has been provided in the standard lib within the package `slices` under the
|
||||||
|
// name Concat since GO version 1.21 onwards. As lancet commits to compatibility with GO
|
||||||
|
// 1.18 onwards, we implement the functionality as an internal function.
|
||||||
|
func concat[S ~[]E, E any](slices ...S) S {
|
||||||
|
size := 0
|
||||||
|
for _, s := range slices {
|
||||||
|
size += len(s)
|
||||||
|
if size < 0 {
|
||||||
|
panic("len out of range")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Use Grow, not make, to round up to the size class:
|
||||||
|
// the extra space is otherwise unused and helps
|
||||||
|
// callers that append a few elements to the result.
|
||||||
|
newslice := grow[S](nil, size)
|
||||||
|
for _, s := range slices {
|
||||||
|
newslice = append(newslice, s...)
|
||||||
|
}
|
||||||
|
return newslice
|
||||||
|
}
|
||||||
|
|
||||||
|
// grow increases the slice's capacity, if necessary, to guarantee space for
|
||||||
|
// another n elements. After grow(n), at least n elements can be appended
|
||||||
|
// to the slice without another allocation. If n is negative or too large to
|
||||||
|
// allocate the memory, grow panics.
|
||||||
|
//
|
||||||
|
// grow has been provided in the standard lib within the package `slices` under the
|
||||||
|
// name Grow since GO version 1.21 onwards. As lancet commits to compatibility with GO
|
||||||
|
// 1.18 onwards, we implement the functionality as an internal function.
|
||||||
|
func grow[S ~[]E, E any](s S, n int) S {
|
||||||
|
if n < 0 {
|
||||||
|
panic("cannot be negative")
|
||||||
|
}
|
||||||
|
if n -= cap(s) - len(s); n > 0 {
|
||||||
|
// This expression allocates only once.
|
||||||
|
s = append(s[:cap(s)], make([]E, n)...)[:len(s)]
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|||||||
@@ -1008,7 +1008,7 @@ func TestUniqueByComparator(t *testing.T) {
|
|||||||
t.Run("case-insensitive string comparison", func(t *testing.T) {
|
t.Run("case-insensitive string comparison", func(t *testing.T) {
|
||||||
stringSlice := []string{"apple", "banana", "Apple", "cherry", "Banana", "date"}
|
stringSlice := []string{"apple", "banana", "Apple", "cherry", "Banana", "date"}
|
||||||
caseInsensitiveComparator := func(item, other string) bool {
|
caseInsensitiveComparator := func(item, other string) bool {
|
||||||
return strings.ToLower(item) == strings.ToLower(other)
|
return strings.EqualFold(item, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
result := UniqueByComparator(stringSlice, caseInsensitiveComparator)
|
result := UniqueByComparator(stringSlice, caseInsensitiveComparator)
|
||||||
@@ -1756,6 +1756,20 @@ func TestRightPaddingAndLeftPadding(t *testing.T) {
|
|||||||
|
|
||||||
padded := LeftPadding(RightPadding(nums, 0, 3), 0, 3)
|
padded := LeftPadding(RightPadding(nums, 0, 3), 0, 3)
|
||||||
assert.Equal([]int{0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0}, padded)
|
assert.Equal([]int{0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0}, padded)
|
||||||
|
|
||||||
|
// Test with negative padding length
|
||||||
|
paddedNegative := LeftPadding(RightPadding(nums, 0, -3), 0, -3)
|
||||||
|
assert.Equal([]int{1, 2, 3, 4, 5}, paddedNegative)
|
||||||
|
|
||||||
|
// Test with empty slice
|
||||||
|
empty := []int{}
|
||||||
|
paddedEmpty := LeftPadding(RightPadding(empty, 0, 3), 0, 3)
|
||||||
|
assert.Equal([]int{0, 0, 0, 0, 0, 0}, paddedEmpty)
|
||||||
|
|
||||||
|
// Test with nil
|
||||||
|
nilSlice := []int(nil)
|
||||||
|
paddedNil := LeftPadding(RightPadding(nilSlice, 0, 3), 0, 3)
|
||||||
|
assert.Equal([]int{0, 0, 0, 0, 0, 0}, paddedNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUniqueByConcurrent(t *testing.T) {
|
func TestUniqueByConcurrent(t *testing.T) {
|
||||||
|
|||||||
@@ -39,10 +39,26 @@ var (
|
|||||||
visaMatcher *regexp.Regexp = regexp.MustCompile(`^4[0-9]{12}(?:[0-9]{3})?$`)
|
visaMatcher *regexp.Regexp = regexp.MustCompile(`^4[0-9]{12}(?:[0-9]{3})?$`)
|
||||||
masterCardMatcher *regexp.Regexp = regexp.MustCompile(`^5[1-5][0-9]{14}$`)
|
masterCardMatcher *regexp.Regexp = regexp.MustCompile(`^5[1-5][0-9]{14}$`)
|
||||||
americanExpressMatcher *regexp.Regexp = regexp.MustCompile(`^3[47][0-9]{13}$`)
|
americanExpressMatcher *regexp.Regexp = regexp.MustCompile(`^3[47][0-9]{13}$`)
|
||||||
unionPay *regexp.Regexp = regexp.MustCompile("^62[0-5]\\d{13,16}$")
|
unionPayMatcher *regexp.Regexp = regexp.MustCompile(`^62[0-5]\\d{13,16}$`)
|
||||||
chinaUnionPay *regexp.Regexp = regexp.MustCompile(`^62[0-9]{14,17}$`)
|
chinaUnionPayMatcher *regexp.Regexp = regexp.MustCompile(`^62[0-9]{14,17}$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var passportMatcher = map[string]*regexp.Regexp{
|
||||||
|
"CN": regexp.MustCompile(`^P\d{9}$`),
|
||||||
|
"US": regexp.MustCompile(`^\d{9}$`),
|
||||||
|
"GB": regexp.MustCompile(`^[A-Z0-9]{9}$`),
|
||||||
|
"RU": regexp.MustCompile(`^[A-Z]{2}\d{7}$`),
|
||||||
|
"DE": regexp.MustCompile(`^\d{9}$`),
|
||||||
|
"FR": regexp.MustCompile(`^[A-Z]{2}\d{7}$`),
|
||||||
|
"JP": regexp.MustCompile(`^\d{8}$`),
|
||||||
|
"IT": regexp.MustCompile(`^\d{8}$`),
|
||||||
|
"AU": regexp.MustCompile(`^[A-Z]{1}\d{8}$`),
|
||||||
|
"BR": regexp.MustCompile(`^\d{9}$`),
|
||||||
|
"IN": regexp.MustCompile(`^[A-Z]{1,2}\d{7}$`),
|
||||||
|
"HK": regexp.MustCompile(`^M\d{8}$`),
|
||||||
|
"MO": regexp.MustCompile(`^[A-Z]\d{8}$`),
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Identity card formula
|
// Identity card formula
|
||||||
factor = [17]int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
|
factor = [17]int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
|
||||||
@@ -460,12 +476,13 @@ func IsZeroValue(value any) bool {
|
|||||||
func IsGBK(data []byte) bool {
|
func IsGBK(data []byte) bool {
|
||||||
i := 0
|
i := 0
|
||||||
for i < len(data) {
|
for i < len(data) {
|
||||||
if data[i] <= 0xff {
|
if data[i] < 0x81 {
|
||||||
i++
|
i++
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
if data[i] >= 0x81 &&
|
if data[i] >= 0x81 &&
|
||||||
data[i] <= 0xfe &&
|
data[i] <= 0xfe &&
|
||||||
|
i+1 < len(data) &&
|
||||||
data[i+1] >= 0x40 &&
|
data[i+1] >= 0x40 &&
|
||||||
data[i+1] <= 0xfe &&
|
data[i+1] <= 0xfe &&
|
||||||
data[i+1] != 0xf7 {
|
data[i+1] != 0xf7 {
|
||||||
@@ -562,11 +579,22 @@ func IsAmericanExpress(v string) bool {
|
|||||||
// IsUnionPay check if a give string is a valid union pay nubmer or not.
|
// IsUnionPay check if a give string is a valid union pay nubmer or not.
|
||||||
// Play: https://go.dev/play/p/CUHPEwEITDf
|
// Play: https://go.dev/play/p/CUHPEwEITDf
|
||||||
func IsUnionPay(v string) bool {
|
func IsUnionPay(v string) bool {
|
||||||
return unionPay.MatchString(v)
|
return unionPayMatcher.MatchString(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsChinaUnionPay check if a give string is a valid china union pay nubmer or not.
|
// IsChinaUnionPay check if a give string is a valid china union pay nubmer or not.
|
||||||
// Play: https://go.dev/play/p/yafpdxLiymu
|
// Play: https://go.dev/play/p/yafpdxLiymu
|
||||||
func IsChinaUnionPay(v string) bool {
|
func IsChinaUnionPay(v string) bool {
|
||||||
return chinaUnionPay.MatchString(v)
|
return chinaUnionPayMatcher.MatchString(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPassport checks if the passport number is valid for a given country.
|
||||||
|
// country is a two-letter country code (ISO 3166-1 alpha-2).
|
||||||
|
// Play: todo
|
||||||
|
func IsPassport(passport, country string) bool {
|
||||||
|
if matcher, ok := passportMatcher[country]; ok {
|
||||||
|
return matcher.MatchString(passport)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -683,3 +683,21 @@ func ExampleIsAlphaNumeric() {
|
|||||||
// true
|
// true
|
||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleIsPassport() {
|
||||||
|
result1 := IsPassport("P123456789", "CN")
|
||||||
|
result2 := IsPassport("123456789", "US")
|
||||||
|
result3 := IsPassport("AB1234567", "RU")
|
||||||
|
result4 := IsPassport("123456789", "CN")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|||||||
@@ -924,3 +924,33 @@ func TestIsAlphaNumeric(t *testing.T) {
|
|||||||
assert.Equal(tt.expected, IsAlphaNumeric(tt.input))
|
assert.Equal(tt.expected, IsAlphaNumeric(tt.input))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsPassport(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestIsPassport")
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
passport string
|
||||||
|
countryCode string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{"P123456789", "CN", true},
|
||||||
|
{"123456789", "US", true},
|
||||||
|
{"A12345678", "GB", true},
|
||||||
|
{"AB1234567", "FR", true},
|
||||||
|
{"12345678", "JP", true},
|
||||||
|
{"M12345678", "HK", true},
|
||||||
|
{"A12345678", "MO", true},
|
||||||
|
{"A1234567", "IN", true},
|
||||||
|
{"12345678", "IT", true},
|
||||||
|
{"A12345678", "AU", true},
|
||||||
|
{"123456789", "BR", true},
|
||||||
|
{"AB1234567", "RU", true},
|
||||||
|
{"123456789", "CN", false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
assert.Equal(tt.expected, IsPassport(tt.passport, tt.countryCode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user