feat: sher 包增加部分转换和去重相关函数

This commit is contained in:
kercylan98 2024-01-04 10:39:34 +08:00
parent 3e41068619
commit 2ff360c48c
5 changed files with 257 additions and 11 deletions

View File

@ -452,7 +452,7 @@ func (srv *Server) low(message *Message, present time.Time, expect time.Duration
fields = append(fields, log.String("type", messageNames[message.t]), log.String("cost", cost.String()), log.String("message", message.String()))
fields = append(fields, message.marks...)
//fields = append(fields, log.Stack("stack"))
log.Warn("ServerLowMessage", sher.SliceCastToAny(fields)...)
log.Warn("ServerLowMessage", sher.ConvertSliceToAny(fields)...)
srv.OnMessageLowExecEvent(message, cost)
}
}

View File

@ -1,10 +0,0 @@
package sher
// SliceCastToAny 将切片转换为任意类型的切片
func SliceCastToAny[S ~[]V, V any](s S) []any {
var r = make([]any, len(s))
for i, v := range s {
r[i] = v
}
return r
}

55
utils/sher/convert.go Normal file
View File

@ -0,0 +1,55 @@
package sher
// ConvertSliceToAny 将切片转换为任意类型的切片
func ConvertSliceToAny[S ~[]V, V any](s S) []any {
var r = make([]any, len(s))
for i, v := range s {
r[i] = v
}
return r
}
// ConvertSliceToIndexMap 将切片转换为索引为键的映射
func ConvertSliceToIndexMap[S ~[]V, V any](s S) map[int]V {
var r = make(map[int]V, len(s))
for i, v := range s {
r[i] = v
}
return r
}
// ConvertSliceToMap 将切片转换为值为键的映射
func ConvertSliceToMap[S ~[]V, V comparable](s S) map[V]struct{} {
var r = make(map[V]struct{}, len(s))
for _, v := range s {
r[v] = struct{}{}
}
return r
}
// ConvertSliceToBoolMap 将切片转换为值为键的映射
func ConvertSliceToBoolMap[S ~[]V, V comparable](s S) map[V]bool {
var r = make(map[V]bool, len(s))
for _, v := range s {
r[v] = true
}
return r
}
// ConvertMapKeysToSlice 将映射的键转换为切片
func ConvertMapKeysToSlice[M ~map[K]V, K comparable, V any](m M) []K {
var r = make([]K, 0, len(m))
for k := range m {
r = append(r, k)
}
return r
}
// ConvertMapValuesToSlice 将映射的值转换为切片
func ConvertMapValuesToSlice[M ~map[K]V, K comparable, V any](m M) []V {
var r = make([]V, 0, len(m))
for _, v := range m {
r = append(r, v)
}
return r
}

83
utils/sher/duplicate.go Normal file
View File

@ -0,0 +1,83 @@
package sher
// DeduplicateSliceInPlace 去除切片中的重复元素
func DeduplicateSliceInPlace[S ~[]V, V comparable](s *S) {
if s == nil || len(*s) < 2 {
return
}
var m = make(map[V]struct{}, len(*s))
var writeIndex int
for readIndex, v := range *s {
if _, ok := m[v]; !ok {
(*s)[writeIndex] = (*s)[readIndex]
writeIndex++
m[v] = struct{}{}
}
}
*s = (*s)[:writeIndex]
}
// DeduplicateSlice 去除切片中的重复元素,返回新切片
func DeduplicateSlice[S ~[]V, V comparable](s S) S {
if s == nil || len(s) < 2 {
return any(s).(S)
}
var r = make([]V, 0, len(s))
var m = make(map[V]struct{}, len(s))
for _, v := range s {
if _, ok := m[v]; !ok {
r = append(r, v)
m[v] = struct{}{}
}
}
return r
}
// DeduplicateSliceInPlaceWithCompare 去除切片中的重复元素,使用自定义的比较函数
func DeduplicateSliceInPlaceWithCompare[S ~[]V, V any](s *S, compare func(a, b V) bool) {
if s == nil || len(*s) < 2 {
return
}
seen := make(map[int]struct{})
resultIndex := 0
for i := range *s {
unique := true
for j := range seen {
if compare((*s)[i], (*s)[j]) {
unique = false // Found a duplicate
break
}
}
if unique {
seen[i] = struct{}{}
(*s)[resultIndex] = (*s)[i]
resultIndex++
}
}
*s = (*s)[:resultIndex]
}
// DeduplicateSliceWithCompare 去除切片中的重复元素,使用自定义的比较函数,返回新的切片
func DeduplicateSliceWithCompare[S ~[]V, V any](s S, compare func(a, b V) bool) S {
if s == nil || compare == nil || len(s) < 2 {
return s
}
seen := make(map[int]struct{})
var result = make([]V, 0, len(s))
for i := range s {
unique := true
for j := range result {
if compare(s[i], result[j]) {
unique = false
break
}
}
if unique {
result = append(result, s[i])
seen[i] = struct{}{}
}
}
return result
}

View File

@ -0,0 +1,118 @@
package sher_test
import (
"github.com/kercylan98/minotaur/utils/sher"
"testing"
)
func TestDeduplicateSliceInPlace(t *testing.T) {
var cases = []struct {
s []int
expected []int
}{
{
s: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
},
{
s: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 1},
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
},
{
s: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2},
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
},
}
for _, c := range cases {
sher.DeduplicateSliceInPlace(&c.s)
if len(c.s) != len(c.expected) {
t.Errorf("DeduplicateSliceInPlace(%v) == %v, expected %v", c.s, c.s, c.expected)
}
}
}
func TestDeduplicateSlice(t *testing.T) {
var cases = []struct {
s []int
expected []int
}{
{
s: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
},
{
s: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 1},
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
},
{
s: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2},
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
},
}
for _, c := range cases {
sl := len(c.s)
if r := sher.DeduplicateSlice(c.s); len(r) != len(c.expected) || len(c.s) != sl {
t.Errorf("DeduplicateSlice(%v) == %v, expected %v", c.s, r, c.expected)
}
}
}
func TestDeduplicateSliceInPlaceWithCompare(t *testing.T) {
var cases = []struct {
s []int
expected []int
}{
{
s: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
},
{
s: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 1},
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
},
{
s: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2},
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
},
}
for _, c := range cases {
sher.DeduplicateSliceInPlaceWithCompare(&c.s, func(a, b int) bool {
return a == b
})
if len(c.s) != len(c.expected) {
t.Errorf("DeduplicateSliceInPlaceWithCompare(%v) == %v, expected %v", c.s, c.s, c.expected)
}
}
}
func TestDeduplicateSliceWithCompare(t *testing.T) {
var cases = []struct {
s []int
expected []int
}{
{
s: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
},
{
s: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 1},
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
},
{
s: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2},
expected: []int{1, 2, 3, 4, 5, 6, 7, 8, 9},
},
}
for _, c := range cases {
sl := len(c.s)
if r := sher.DeduplicateSliceWithCompare(c.s, func(a, b int) bool {
return a == b
}); len(r) != len(c.expected) || len(c.s) != sl {
t.Errorf("DeduplicateSliceWithCompare(%v) == %v, expected %v", c.s, r, c.expected)
}
}
}