feat: sher 包增加部分转换和去重相关函数
This commit is contained in:
parent
3e41068619
commit
2ff360c48c
|
@ -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, log.String("type", messageNames[message.t]), log.String("cost", cost.String()), log.String("message", message.String()))
|
||||||
fields = append(fields, message.marks...)
|
fields = append(fields, message.marks...)
|
||||||
//fields = append(fields, log.Stack("stack"))
|
//fields = append(fields, log.Stack("stack"))
|
||||||
log.Warn("ServerLowMessage", sher.SliceCastToAny(fields)...)
|
log.Warn("ServerLowMessage", sher.ConvertSliceToAny(fields)...)
|
||||||
srv.OnMessageLowExecEvent(message, cost)
|
srv.OnMessageLowExecEvent(message, cost)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue