diff --git a/cryptor/rsa_private_example.pem b/cryptor/rsa_private_example.pem index a0b8f89..ada0b1c 100644 --- a/cryptor/rsa_private_example.pem +++ b/cryptor/rsa_private_example.pem @@ -1,51 +1,51 @@ -----BEGIN rsa private key----- -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 -----END rsa private key----- diff --git a/cryptor/rsa_public_example.pem b/cryptor/rsa_public_example.pem index a05d879..824277b 100644 --- a/cryptor/rsa_public_example.pem +++ b/cryptor/rsa_public_example.pem @@ -1,14 +1,14 @@ -----BEGIN rsa public key----- -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwUdYQvqsym2r86Xlcu8C -zK6MAjtZH3aW/BsfZ852dra1nYGqUoJMe31eiurN9BK/OXmo7D3zm3OCCl/uGUCi -NgWKYAfaW2o4rFE7tHwHf5E4/bLmp2c6+xwP5bSo6r0pXonszPpMK4sTHNxgaXLh -HYdx1dKXWt5SvHXo012fWsXTC7MQrpTeQIOZViC3ldQpXO026nKzwzgr7WW9kZak -HYPz0IdwQGkl6/EY3LpnP3ADsop9HWZmTIcZUfaztdwnC9JS4zJg1gGMioQXgavl -POVEDmXk8Oi+1ORB6CphlovSeuT9IxIoSlv77ARazKZcTfnxzXgpPT2wBdiGiTvq -2/vON1IvjDPd4MkBYEx3k5tbdL//HjzkKlg/zElELvrXEQFpdvzCdrqrTDQ56ej1 -A5AH1q6eIJULh5hhq5jLIxkSYiiCrXYlTSPX7D9t7PLHj5AVv2PkHhuU1pwv7HnL -sPfTwxYcxjygLP8lJPPE+y8UJLFCOUKkPr9dGLqA8G6ZvWhYHTyiwVEENwb+RdV2 -lakg7YNgRfEymvY3HqiiZiH8T7eOc1tt/eF3gDbG2jjlD83cxYetYFNgtSk/+0gy -dBQKRR+w8PUTdLb1ZZhzk/7yZCrrsh043967ECjNI5hyvSYdR+sj3W9i39Jj/4JS -X05C9FKEAehvubw9V/AMXcMCAwEAAQ== +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoJVrCBR3dJsdj0Gg9tlk +ToGvywJnJqVWBPgjnS+Hn5Ksxk1yzBieL0aQ84hVXYt0yhCgiDl/eDmgdawqUZ5j +2PhFBDahjvBnchY2ViZXNE61ya3YPEPIwUsZ1Wsmzu5cX6gA1HqE2nx8iZlJQcbG +/rdoxyebhdvUj6iGGvgskggkVYvDYuct+iRekfHMxG3ON+wJ31AC2+0B6w6vgvt1 +1uZpAnG/lR2APzTxnDHVHEXGmTticlb3ko4zRvTREsY4zSFSq0Io5K29ooYw/pHv +hw3hvirRzjYkaxK5yzLCw788FkRLjpO4yuTYxD3pQ6HpfMMpTl9nCK3IOMqbyaX2 +espY0zmJr/vqbWgqzSlyptXDW80/mAn1nDhQe1qkTW94gqL9GKhGtydFCOKxfIM7 +Y5X7DlMXc1kbup5pw3p8xkltD4KNcG+QuePPIvFp05oiLAHZpO0d3i2pAtiVyQ+7 +YvlEQlqw0LCz8MaDRGZg4+Q3nxPtmg4z7Ms8gsZaKFiyRZCMOg6NEDFwhZPAFJ+6 +JH6Pnbq244LkKYCJNuZpp9rYeOWIIMNevQyHc6iorInnSGJfzxz347NfwV2fcn4b +gQGPbHJOMNDlHnVZgp2ONlVvaSC6DWWE1iGNmOcNcc09PJV87qf8x9SI5FXipsvn +fiVynueMcgSwqQRddt4O408CAwEAAQ== -----END rsa public key----- diff --git a/slice/slice.go b/slice/slice.go index cb19919..1264c0c 100644 --- a/slice/slice.go +++ b/slice/slice.go @@ -59,16 +59,18 @@ func ContainSubSlice[T comparable](slice, subSlice []T) bool { return false } - elementMap := make(map[T]struct{}, len(slice)) + elementCount := make(map[T]int, len(slice)) for _, item := range slice { - elementMap[item] = struct{}{} + elementCount[item]++ } for _, item := range subSlice { - if _, ok := elementMap[item]; !ok { + if elementCount[item] == 0 { return false } + elementCount[item]-- } + return true } @@ -81,14 +83,18 @@ func Chunk[T any](slice []T, size int) [][]T { return result } - for _, item := range slice { - l := len(result) - if l == 0 || len(result[l-1]) == size { - result = append(result, []T{}) - l++ - } + currentChunk := []T{} - result[l-1] = append(result[l-1], item) + for _, item := range slice { + if len(currentChunk) == size { + result = append(result, currentChunk) + currentChunk = []T{} + } + currentChunk = append(currentChunk, item) + } + + if len(currentChunk) > 0 { + result = append(result, currentChunk) } return result @@ -106,6 +112,7 @@ func Compact[T comparable](slice []T) []T { result = append(result, v) } } + return result[:len(result):len(result)] } @@ -133,8 +140,17 @@ func Concat[T any](slices ...[]T) []T { func Difference[T comparable](slice, comparedSlice []T) []T { result := []T{} + if len(slice) == 0 { + return result + } + + comparedMap := make(map[T]struct{}, len(comparedSlice)) + for _, v := range comparedSlice { + comparedMap[v] = struct{}{} + } + for _, v := range slice { - if !Contain(comparedSlice, v) { + if _, found := comparedMap[v]; !found { result = append(result, v) } } @@ -147,13 +163,17 @@ func Difference[T comparable](slice, comparedSlice []T) []T { // like lodash.js differenceBy: https://lodash.com/docs/4.17.15#differenceBy. // Play: https://go.dev/play/p/DiivgwM5OnC func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(index int, item T) T) []T { - orginSliceAfterMap := Map(slice, iteratee) - comparedSliceAfterMap := Map(comparedSlice, iteratee) - result := make([]T, 0) - for i, v := range orginSliceAfterMap { - if !Contain(comparedSliceAfterMap, v) { - result = append(result, slice[i]) + + comparedMap := make(map[T]struct{}, len(comparedSlice)) + for _, item := range comparedSlice { + comparedMap[iteratee(0, item)] = struct{}{} + } + + for i, item := range slice { + transformedItem := iteratee(i, item) + if _, found := comparedMap[transformedItem]; !found { + result = append(result, item) } } @@ -165,23 +185,32 @@ func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(inde // The comparator is invoked with two arguments: (arrVal, othVal). // Play: https://go.dev/play/p/v2U2deugKuV func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(item1, item2 T) bool) []T { - result := make([]T, 0) - getIndex := func(arr []T, item T, comparison func(v1, v2 T) bool) int { - index := -1 for i, v := range arr { if comparison(item, v) { - index = i + return i + } + } + return -1 + } + + result := make([]T, 0, len(slice)) + + comparedMap := make(map[int]T, len(comparedSlice)) + for _, v := range comparedSlice { + comparedMap[getIndex(comparedSlice, v, comparator)] = v + } + + for _, v := range slice { + found := false + for _, existing := range comparedSlice { + if comparator(v, existing) { + found = true break } } - return index - } - - for i, v := range slice { - index := getIndex(comparedSlice, v, comparator) - if index == -1 { - result = append(result, slice[i]) + if !found { + result = append(result, v) } } @@ -423,19 +452,20 @@ func FindLastBy[T any](slice []T, predicate func(index int, item T) bool) (v T, // Flatten flattens slice with one level. // Play: https://go.dev/play/p/hYa3cBEevtm func Flatten(slice any) any { - sv := sliceValue(slice) - - var result reflect.Value - if sv.Type().Elem().Kind() == reflect.Interface { - result = reflect.MakeSlice(reflect.TypeOf([]interface{}{}), 0, sv.Len()) - } else if sv.Type().Elem().Kind() == reflect.Slice { - result = reflect.MakeSlice(sv.Type().Elem(), 0, sv.Len()) - } else { - return result + sv := reflect.ValueOf(slice) + if sv.Kind() != reflect.Slice { + panic("Flatten: input must be a slice") } + elemType := sv.Type().Elem() + if elemType.Kind() == reflect.Slice { + elemType = elemType.Elem() + } + + result := reflect.MakeSlice(reflect.SliceOf(elemType), 0, sv.Len()) + for i := 0; i < sv.Len(); i++ { - item := reflect.ValueOf(sv.Index(i).Interface()) + item := sv.Index(i) if item.Kind() == reflect.Slice { for j := 0; j < item.Len(); j++ { result = reflect.Append(result, item.Index(j)) @@ -607,7 +637,7 @@ func Repeat[T any](item T, n int) []T { } // InterfaceSlice convert param to slice of interface. -// This function is deprecated, use generics feature of go1.18+ for replacement. +// deprecated: use generics feature of go1.18+ for replacement. // Play: https://go.dev/play/p/FdQXF0Vvqs- func InterfaceSlice(slice any) []any { sv := sliceValue(slice) @@ -624,7 +654,7 @@ func InterfaceSlice(slice any) []any { } // StringSlice convert param to slice of string. -// This function is deprecated, use generics feature of go1.18+ for replacement. +// deprecated: use generics feature of go1.18+ for replacement. // Play: https://go.dev/play/p/W0TZDWCPFcI func StringSlice(slice any) []string { v := sliceValue(slice) @@ -642,7 +672,7 @@ func StringSlice(slice any) []string { } // IntSlice convert param to slice of int. -// This function is deprecated, use generics feature of go1.18+ for replacement. +// deprecated: use generics feature of go1.18+ for replacement. // Play: https://go.dev/play/p/UQDj-on9TGN func IntSlice(slice any) []int { sv := sliceValue(slice) @@ -773,46 +803,54 @@ func InsertAt[T any](slice []T, index int, value any) []T { return slice } - if v, ok := value.(T); ok { - slice = append(slice[:index], append([]T{v}, slice[index:]...)...) + switch v := value.(type) { + case T: + result := make([]T, size+1) + copy(result, slice[:index]) + result[index] = v + copy(result[index+1:], slice[index:]) + return result + case []T: + result := make([]T, size+len(v)) + copy(result, slice[:index]) + copy(result[index:], v) + copy(result[index+len(v):], slice[index:]) + return result + default: return slice } - - if v, ok := value.([]T); ok { - slice = append(slice[:index], append(v, slice[index:]...)...) - return slice - } - - return slice } // UpdateAt update the slice element at index. // Play: https://go.dev/play/p/f3mh2KloWVm func UpdateAt[T any](slice []T, index int, value T) []T { - size := len(slice) - - if index < 0 || index >= size { + if index < 0 || index >= len(slice) { return slice } - slice = append(slice[:index], append([]T{value}, slice[index+1:]...)...) - return slice + result := make([]T, len(slice)) + copy(result, slice) + + result[index] = value + + return result } // Unique remove duplicate elements in slice. // Play: https://go.dev/play/p/AXw0R3ZTE6a func Unique[T comparable](slice []T) []T { - result := make([]T, 0, len(slice)) + if len(slice) == 0 { + return slice + } + seen := make(map[T]struct{}, len(slice)) + result := slice[:0] - for i := range slice { - if _, ok := seen[slice[i]]; ok { - continue + for _, item := range slice { + if _, exists := seen[item]; !exists { + seen[item] = struct{}{} + result = append(result, item) } - - seen[slice[i]] = struct{}{} - - result = append(result, slice[i]) } return result @@ -822,18 +860,19 @@ func Unique[T comparable](slice []T) []T { // The function maintains the order of the elements. // Play: https://go.dev/play/p/GY7JE4yikrl func UniqueBy[T any, U comparable](slice []T, iteratee func(item T) U) []T { - result := make([]T, 0, len(slice)) + if len(slice) == 0 { + return slice + } + seen := make(map[U]struct{}, len(slice)) + result := slice[:0] - for i := range slice { - key := iteratee(slice[i]) - if _, ok := seen[key]; ok { - continue + for _, item := range slice { + key := iteratee(item) + if _, exists := seen[key]; !exists { + seen[key] = struct{}{} + result = append(result, item) } - - seen[key] = struct{}{} - - result = append(result, slice[i]) } return result @@ -843,19 +882,20 @@ func UniqueBy[T any, U comparable](slice []T, iteratee func(item T) U) []T { // The function maintains the order of the elements. // Play: https://go.dev/play/p/rwSacr-ZHsR func UniqueByComparator[T comparable](slice []T, comparator func(item T, other T) bool) []T { - result := make([]T, 0, len(slice)) - seen := make([]T, 0, len(slice)) + if len(slice) == 0 { + return slice + } + result := make([]T, 0, len(slice)) for _, item := range slice { - duplicate := false - for _, seenItem := range seen { - if comparator(item, seenItem) { - duplicate = true + isDuplicate := false + for _, existing := range result { + if comparator(item, existing) { + isDuplicate = true break } } - if !duplicate { - seen = append(seen, item) + if !isDuplicate { result = append(result, item) } }