Skip to content

Commit

Permalink
feat: 新增 utils/sher 包,包含了对 slice 及 hash 常用的操作函数。用于未来对 utils/slice 和 u…
Browse files Browse the repository at this point in the history
…tils/hash 包进行替换
  • Loading branch information
kercylan98 committed Dec 29, 2023
1 parent a7b0497 commit 515cbc6
Show file tree
Hide file tree
Showing 8 changed files with 971 additions and 0 deletions.
88 changes: 88 additions & 0 deletions utils/sher/clone.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package sher

import (
"slices"
)

// CloneMatrix 克隆二维数组
func CloneMatrix[S ~[][]V, V any](slice S) S {
if slice == nil {
return nil
}

var result = make(S, len(slice))
for i := 0; i < len(slice); i++ {
result[i] = CloneSlice(slice[i])
}
return result
}

// CloneSlice 克隆切片,该函数是 slices.Clone 的快捷方式
func CloneSlice[S ~[]V, V any](slice S) S {
return slices.Clone(slice)
}

// CloneMap 克隆 map
func CloneMap[M ~map[K]V, K comparable, V any](m M) M {
if m == nil {
return nil
}

var result = make(M, len(m))
for k, v := range m {
result[k] = v
}
return result
}

// CloneSliceN 克隆切片为 n 个切片进行返回
func CloneSliceN[S ~[]V, V any](slice S, n int) []S {
if slice == nil {
return nil
}

var result = make([]S, n)
for i := 0; i < n; i++ {
result[i] = CloneSlice(slice)
}
return result
}

// CloneMapN 克隆 map 为 n 个 map 进行返回
func CloneMapN[M ~map[K]V, K comparable, V any](m M, n int) []M {
if m == nil {
return nil
}

var result = make([]M, n)
for i := 0; i < n; i++ {
result[i] = CloneMap(m)
}
return result
}

// CloneSlices 克隆多个切片
func CloneSlices[S ~[]V, V any](slices ...S) []S {
if slices == nil {
return nil
}

var result = make([]S, len(slices))
for i, slice := range slices {
result[i] = CloneSlice(slice)
}
return result
}

// CloneMaps 克隆多个 map
func CloneMaps[M ~map[K]V, K comparable, V any](maps ...M) []M {
if maps == nil {
return nil
}

var result = make([]M, len(maps))
for i, m := range maps {
result[i] = CloneMap(m)
}
return result
}
308 changes: 308 additions & 0 deletions utils/sher/contains.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,308 @@
package sher

import "sort"

type ComparisonHandler[V any] func(source, target V) bool

// InSlice 判断切片中是否包含某个元素
func InSlice[S ~[]V, V any](slice S, v V, handler ComparisonHandler[V]) bool {
if slice == nil {
return false
}
for _, value := range slice {
if handler(v, value) {
return true
}
}
return false
}

// InSliceByBinarySearch 判断切片中是否包含某个元素,使用二分搜索
func InSliceByBinarySearch[S ~[]V, V any](slice S, v V, handler ComparisonHandler[V]) bool {
return sort.Search(len(slice), func(i int) bool {
return handler(v, slice[i])
}) != len(slice)
}

// AllInSlice 判断切片中是否包含所有元素
func AllInSlice[S ~[]V, V any](slice S, values []V, handler ComparisonHandler[V]) bool {
if slice == nil {
return false
}
for _, value := range values {
if !InSlice(slice, value, handler) {
return false
}
}
return true
}

// AllInSliceByBinarySearch 判断切片中是否包含所有元素,使用二分搜索
func AllInSliceByBinarySearch[S ~[]V, V any](slice S, values []V, handler ComparisonHandler[V]) bool {
if slice == nil {
return false
}
for _, value := range values {
if !InSliceByBinarySearch(slice, value, handler) {
return false
}
}
return true
}

// AnyInSlice 判断切片中是否包含任意一个元素
func AnyInSlice[S ~[]V, V any](slice S, values []V, handler ComparisonHandler[V]) bool {
if slice == nil {
return false
}
for _, value := range values {
if InSlice(slice, value, handler) {
return true
}
}
return false
}

// AnyInSliceByBinarySearch 判断切片中是否包含任意一个元素,使用二分搜索
func AnyInSliceByBinarySearch[S ~[]V, V any](slice S, values []V, handler ComparisonHandler[V]) bool {
if slice == nil {
return false
}
for _, value := range values {
if InSliceByBinarySearch(slice, value, handler) {
return true
}
}
return false
}

// InSlices 判断多个切片中是否包含某个元素
func InSlices[S ~[]V, V any](slices []S, v V, handler ComparisonHandler[V]) bool {
return InSlice(MergeSlices(slices...), v, handler)
}

// InSlicesByBinarySearch 判断多个切片中是否包含某个元素,使用二分搜索
func InSlicesByBinarySearch[S ~[]V, V any](slices []S, v V, handler ComparisonHandler[V]) bool {
return InSliceByBinarySearch(MergeSlices(slices...), v, handler)
}

// AllInSlices 判断多个切片中是否包含所有元素
func AllInSlices[S ~[]V, V any](slices []S, values []V, handler ComparisonHandler[V]) bool {
return AllInSlice(MergeSlices(slices...), values, handler)
}

// AllInSlicesByBinarySearch 判断多个切片中是否包含所有元素,使用二分搜索
func AllInSlicesByBinarySearch[S ~[]V, V any](slices []S, values []V, handler ComparisonHandler[V]) bool {
return AllInSliceByBinarySearch(MergeSlices(slices...), values, handler)
}

// AnyInSlices 判断多个切片中是否包含任意一个元素
func AnyInSlices[S ~[]V, V any](slices []S, values []V, handler ComparisonHandler[V]) bool {
return AnyInSlice(MergeSlices(slices...), values, handler)
}

// AnyInSlicesByBinarySearch 判断多个切片中是否包含任意一个元素,使用二分搜索
func AnyInSlicesByBinarySearch[S ~[]V, V any](slices []S, values []V, handler ComparisonHandler[V]) bool {
return AnyInSliceByBinarySearch(MergeSlices(slices...), values, handler)
}

// InAllSlices 判断元素是否在所有切片中都存在
func InAllSlices[S ~[]V, V any](slices []S, v V, handler ComparisonHandler[V]) bool {
if slices == nil {
return false
}
for _, slice := range slices {
if !InSlice(slice, v, handler) {
return false
}
}
return true
}

// InAllSlicesByBinarySearch 判断元素是否在所有切片中都存在,使用二分搜索
func InAllSlicesByBinarySearch[S ~[]V, V any](slices []S, v V, handler ComparisonHandler[V]) bool {
if slices == nil {
return false
}
for _, slice := range slices {
if !InSliceByBinarySearch(slice, v, handler) {
return false
}
}
return true
}

// AnyInAllSlices 判断元素是否在所有切片中都存在任意至少一个
func AnyInAllSlices[S ~[]V, V any](slices []S, v []V, handler ComparisonHandler[V]) bool {
if slices == nil {
return false
}
for _, slice := range slices {
if AnyInSlice(slice, v, handler) {
return true
}
}
return false
}

// AnyInAllSlicesByBinarySearch 判断元素是否在所有切片中都存在任意至少一个,使用二分搜索
func AnyInAllSlicesByBinarySearch[S ~[]V, V any](slices []S, v []V, handler ComparisonHandler[V]) bool {
if slices == nil {
return false
}
for _, slice := range slices {
if AnyInSliceByBinarySearch(slice, v, handler) {
return true
}
}
return false
}

// KeyInMap 判断 map 中是否包含某个 key
func KeyInMap[M ~map[K]V, K comparable, V any](m M, key K) bool {
_, ok := m[key]
return ok
}

// ValueInMap 判断 map 中是否包含某个 value
func ValueInMap[M ~map[K]V, K comparable, V any](m M, value V, handler ComparisonHandler[V]) bool {
if m == nil {
return false
}
for _, v := range m {
if handler(value, v) {
return true
}
}
return false
}

// AllKeyInMap 判断 map 中是否包含所有 key
func AllKeyInMap[M ~map[K]V, K comparable, V any](m M, keys ...K) bool {
if m == nil {
return false
}
for _, key := range keys {
if !KeyInMap(m, key) {
return false
}
}
return true
}

// AllValueInMap 判断 map 中是否包含所有 value
func AllValueInMap[M ~map[K]V, K comparable, V any](m M, values []V, handler ComparisonHandler[V]) bool {
if m == nil {
return false
}
for _, value := range values {
if !ValueInMap(m, value, handler) {
return false
}
}
return true
}

// AnyKeyInMap 判断 map 中是否包含任意一个 key
func AnyKeyInMap[M ~map[K]V, K comparable, V any](m M, keys ...K) bool {
if m == nil {
return false
}
for _, key := range keys {
if KeyInMap(m, key) {
return true
}
}
return false
}

// AnyValueInMap 判断 map 中是否包含任意一个 value
func AnyValueInMap[M ~map[K]V, K comparable, V any](m M, values []V, handler ComparisonHandler[V]) bool {
if m == nil {
return false
}
for _, value := range values {
if ValueInMap(m, value, handler) {
return true
}
}
return false
}

// AllKeyInMaps 判断多个 map 中是否包含所有 key
func AllKeyInMaps[M ~map[K]V, K comparable, V any](maps []M, keys ...K) bool {
if maps == nil {
return false
}
for _, m := range maps {
if !AllKeyInMap(m, keys...) {
return false
}
}
return true
}

// AllValueInMaps 判断多个 map 中是否包含所有 value
func AllValueInMaps[M ~map[K]V, K comparable, V any](maps []M, values []V, handler ComparisonHandler[V]) bool {
if maps == nil {
return false
}
for _, m := range maps {
if !AllValueInMap(m, values, handler) {
return false
}
}
return true
}

// AnyKeyInMaps 判断多个 map 中是否包含任意一个 key
func AnyKeyInMaps[M ~map[K]V, K comparable, V any](maps []M, keys ...K) bool {
if maps == nil {
return false
}
for _, m := range maps {
if AnyKeyInMap(m, keys...) {
return true
}
}
return false
}

// AnyValueInMaps 判断多个 map 中是否包含任意一个 value
func AnyValueInMaps[M ~map[K]V, K comparable, V any](maps []M, values []V, handler ComparisonHandler[V]) bool {
if maps == nil {
return false
}
for _, m := range maps {
if AnyValueInMap(m, values, handler) {
return true
}
}
return false
}

// InAllMaps 判断元素是否在所有 map 中都存在
func InAllMaps[M ~map[K]V, K comparable, V any](maps []M, key K) bool {
if maps == nil {
return false
}
for _, m := range maps {
if !KeyInMap(m, key) {
return false
}
}
return true
}

// AnyInAllMaps 判断元素是否在所有 map 中都存在任意至少一个
func AnyInAllMaps[M ~map[K]V, K comparable, V any](maps []M, keys []K) bool {
if maps == nil {
return false
}
for _, m := range maps {
if AnyKeyInMap(m, keys...) {
return true
}
}
return false
}

0 comments on commit 515cbc6

Please sign in to comment.