feat: 新增 steram 包,支持 map 和 slice 的链式操作
This commit is contained in:
parent
8f9589df42
commit
10fcb54322
|
@ -2,7 +2,7 @@ package builtin
|
|||
|
||||
import (
|
||||
"github.com/kercylan98/minotaur/game"
|
||||
"github.com/kercylan98/minotaur/utils/asynchronization"
|
||||
"github.com/kercylan98/minotaur/utils/asynchronous"
|
||||
"github.com/kercylan98/minotaur/utils/hash"
|
||||
"github.com/kercylan98/minotaur/utils/log"
|
||||
"go.uber.org/zap"
|
||||
|
@ -12,7 +12,7 @@ import (
|
|||
func NewRoom[PlayerID comparable, Player game.Player[PlayerID]](guid int64, options ...RoomOption[PlayerID, Player]) *Room[PlayerID, Player] {
|
||||
room := &Room[PlayerID, Player]{
|
||||
guid: guid,
|
||||
players: asynchronization.NewMap[PlayerID, Player](),
|
||||
players: asynchronous.NewMap[PlayerID, Player](),
|
||||
}
|
||||
for _, option := range options {
|
||||
option(room)
|
||||
|
|
|
@ -2,7 +2,7 @@ package builtin
|
|||
|
||||
import (
|
||||
"github.com/kercylan98/minotaur/game"
|
||||
"github.com/kercylan98/minotaur/utils/asynchronization"
|
||||
"github.com/kercylan98/minotaur/utils/asynchronous"
|
||||
"github.com/kercylan98/minotaur/utils/hash"
|
||||
"github.com/kercylan98/minotaur/utils/slice"
|
||||
"sync"
|
||||
|
@ -12,7 +12,7 @@ import (
|
|||
func NewRoomSeat[PlayerID comparable, Player game.Player[PlayerID]](room game.Room[PlayerID, Player], options ...RoomSeatOption[PlayerID, Player]) *RoomSeat[PlayerID, Player] {
|
||||
roomSeat := &RoomSeat[PlayerID, Player]{
|
||||
Room: room,
|
||||
seatPS: asynchronization.NewMap[PlayerID, int](),
|
||||
seatPS: asynchronous.NewMap[PlayerID, int](),
|
||||
}
|
||||
for _, option := range options {
|
||||
option(roomSeat)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package report
|
||||
|
||||
import (
|
||||
"github.com/kercylan98/minotaur/utils/asynchronization"
|
||||
"github.com/kercylan98/minotaur/utils/asynchronous"
|
||||
"github.com/kercylan98/minotaur/utils/hash"
|
||||
"sync"
|
||||
)
|
||||
|
@ -10,7 +10,7 @@ import (
|
|||
func NewDataBuried[DataID comparable, Data any](name string, hitLogic HitLogic[Data], options ...DataBuriedOption[DataID, Data]) *DataBuried[DataID, Data] {
|
||||
buried := &DataBuried[DataID, Data]{
|
||||
name: name,
|
||||
data: asynchronization.NewMap[DataID, Data](),
|
||||
data: asynchronous.NewMap[DataID, Data](),
|
||||
hitLogic: hitLogic,
|
||||
}
|
||||
buried.setData = func(id DataID, data Data) {
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
package asynchronization
|
||||
package asynchronous
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/kercylan98/minotaur/utils/hash"
|
||||
)
|
||||
|
||||
func NewMap[Key comparable, value any]() *Map[Key, value] {
|
||||
return &Map[Key, value]{
|
||||
data: make(map[Key]value),
|
||||
func NewMap[Key comparable, Value any](options ...MapOption[Key, Value]) *Map[Key, Value] {
|
||||
m := &Map[Key, Value]{
|
||||
data: make(map[Key]Value),
|
||||
}
|
||||
for _, option := range options {
|
||||
option(m)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Map 非并发安全的字典数据结构
|
|
@ -0,0 +1,10 @@
|
|||
package asynchronous
|
||||
|
||||
type MapOption[Key comparable, Value any] func(m *Map[Key, Value])
|
||||
|
||||
// WithMapSource 通过传入的 map 初始化
|
||||
func WithMapSource[Key comparable, Value any](source map[Key]Value) MapOption[Key, Value] {
|
||||
return func(m *Map[Key, Value]) {
|
||||
m.data = source
|
||||
}
|
||||
}
|
|
@ -37,3 +37,8 @@ func IntN(n int) int {
|
|||
}
|
||||
return rand.Intn(n)
|
||||
}
|
||||
|
||||
// Bool 返回一个随机的布尔值
|
||||
func Bool() bool {
|
||||
return rand.Intn(2) == 1
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package slice
|
||||
|
||||
import "math/rand"
|
||||
import (
|
||||
"math/rand"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Del 删除特定索引的元素
|
||||
func Del[V any](slice *[]V, index int) {
|
||||
|
@ -98,6 +101,24 @@ func Shuffle[V any](slice []V) {
|
|||
}
|
||||
}
|
||||
|
||||
// Distinct 去重
|
||||
func Distinct[V any](slice []V) []V {
|
||||
var result []V
|
||||
for i := range slice {
|
||||
flag := true
|
||||
for j := range result {
|
||||
if reflect.DeepEqual(slice[i], result[j]) {
|
||||
flag = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if flag {
|
||||
result = append(result, slice[i])
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Swap 交换数组中的两个元素
|
||||
func Swap[V any](slice []V, i, j int) {
|
||||
slice[i], slice[j] = slice[j], slice[i]
|
||||
|
@ -146,7 +167,7 @@ func GetEndPart[V any](slice []V, n int) []V {
|
|||
return slice[len(slice)-n:]
|
||||
}
|
||||
|
||||
// GetPart 获取数组的部分元素
|
||||
// GetPart 获取指定区间的元素
|
||||
func GetPart[V any](slice []V, start, end int) []V {
|
||||
if start < 0 {
|
||||
start = 0
|
||||
|
@ -156,3 +177,23 @@ func GetPart[V any](slice []V, start, end int) []V {
|
|||
}
|
||||
return slice[start:end]
|
||||
}
|
||||
|
||||
// Contains 判断数组是否包含某个元素
|
||||
func Contains[V comparable](slice []V, value V) bool {
|
||||
for _, v := range slice {
|
||||
if v == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ContainsAny 判断数组是否包含某个元素
|
||||
func ContainsAny[V any](slice []V, values V) bool {
|
||||
for _, v := range slice {
|
||||
if reflect.DeepEqual(v, values) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
package stream
|
||||
|
||||
import (
|
||||
"github.com/kercylan98/minotaur/utils/asynchronous"
|
||||
"github.com/kercylan98/minotaur/utils/hash"
|
||||
"github.com/kercylan98/minotaur/utils/synchronization"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// WithMap 使用传入的 map 执行链式操作
|
||||
// - 该函数将会直接影响到传入的 map
|
||||
func WithMap[K comparable, V any](m map[K]V) Map[K, V] {
|
||||
return m
|
||||
}
|
||||
|
||||
// WithMapCopy 使用传入的 map 执行链式操作
|
||||
// - 该函数不会影响到传入的 map
|
||||
func WithMapCopy[K comparable, V any](m map[K]V) Map[K, V] {
|
||||
return hash.Copy(m)
|
||||
}
|
||||
|
||||
// WithHashMap 使用传入的 map 执行链式操作
|
||||
func WithHashMap[K comparable, V any](m hash.Map[K, V]) Map[K, V] {
|
||||
return m.Map()
|
||||
}
|
||||
|
||||
// Map 提供了 map 的链式操作
|
||||
type Map[K comparable, V any] map[K]V
|
||||
|
||||
// Set 设置一个值
|
||||
func (slf Map[K, V]) Set(key K, value V) Map[K, V] {
|
||||
slf[key] = value
|
||||
return slf
|
||||
}
|
||||
|
||||
// Delete 删除一个值
|
||||
func (slf Map[K, V]) Delete(key K) Map[K, V] {
|
||||
delete(slf, key)
|
||||
return slf
|
||||
}
|
||||
|
||||
// Filter 过滤 handle 返回 false 的元素
|
||||
func (slf Map[K, V]) Filter(handle func(key K, value V) bool) Map[K, V] {
|
||||
for k, v := range slf {
|
||||
if !handle(k, v) {
|
||||
delete(slf, k)
|
||||
}
|
||||
}
|
||||
return slf
|
||||
}
|
||||
|
||||
// FilterKey 过滤特定的 key
|
||||
func (slf Map[K, V]) FilterKey(keys ...K) Map[K, V] {
|
||||
for _, key := range keys {
|
||||
delete(slf, key)
|
||||
}
|
||||
return slf
|
||||
}
|
||||
|
||||
// FilterValue 过滤特定的 value
|
||||
func (slf Map[K, V]) FilterValue(values ...V) Map[K, V] {
|
||||
for k, v := range slf {
|
||||
for _, value := range values {
|
||||
if reflect.DeepEqual(v, value) {
|
||||
delete(slf, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
return slf
|
||||
}
|
||||
|
||||
// RandomKeep 随机保留 n 个元素
|
||||
func (slf Map[K, V]) RandomKeep(n int) Map[K, V] {
|
||||
length := len(slf)
|
||||
if n >= length {
|
||||
return slf
|
||||
}
|
||||
for k := range slf {
|
||||
if n > 0 {
|
||||
n--
|
||||
} else {
|
||||
delete(slf, k)
|
||||
}
|
||||
}
|
||||
return slf
|
||||
}
|
||||
|
||||
// RandomDelete 随机删除 n 个元素
|
||||
func (slf Map[K, V]) RandomDelete(n int) Map[K, V] {
|
||||
var count int
|
||||
for k := range slf {
|
||||
if count < n {
|
||||
count++
|
||||
delete(slf, k)
|
||||
} else {
|
||||
return slf
|
||||
}
|
||||
}
|
||||
return slf
|
||||
}
|
||||
|
||||
// RandomReplace 将 values 覆盖到当前的 map 中
|
||||
// - 如果 values 的长度大于当前 map 的长度,则只会覆盖当前 map 的长度
|
||||
func (slf Map[K, V]) RandomReplace(values ...V) Map[K, V] {
|
||||
var record []K
|
||||
var valuesLen = len(values)
|
||||
for k := range slf {
|
||||
record = append(record, k)
|
||||
if len(record) >= valuesLen {
|
||||
break
|
||||
}
|
||||
}
|
||||
for i, k := range record {
|
||||
slf.Set(k, values[i])
|
||||
}
|
||||
return slf
|
||||
}
|
||||
|
||||
// Distinct 去重,如果 handle 返回 true,则认为是重复的元素
|
||||
func (slf Map[K, V]) Distinct(handle func(key K, value V) bool) Map[K, V] {
|
||||
for k, v := range slf {
|
||||
if handle(k, v) {
|
||||
delete(slf, k)
|
||||
}
|
||||
}
|
||||
return slf
|
||||
}
|
||||
|
||||
// Range 遍历当前 Map, handle 返回 false 则停止遍历
|
||||
func (slf Map[K, V]) Range(handle func(key K, value V) bool) Map[K, V] {
|
||||
for k, v := range slf {
|
||||
if !handle(k, v) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return slf
|
||||
}
|
||||
|
||||
// ValueOr 当 key 不存在时,设置一个默认值
|
||||
func (slf Map[K, V]) ValueOr(key K, value V) Map[K, V] {
|
||||
if _, ok := slf[key]; !ok {
|
||||
slf[key] = value
|
||||
}
|
||||
return slf
|
||||
}
|
||||
|
||||
// GetValueOr 当 key 不存在时,返回一个默认值
|
||||
func (slf Map[K, V]) GetValueOr(key K, value V) V {
|
||||
if v, ok := slf[key]; ok {
|
||||
return v
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// Clear 清空当前 Map
|
||||
func (slf Map[K, V]) Clear() Map[K, V] {
|
||||
for k := range slf {
|
||||
delete(slf, k)
|
||||
}
|
||||
return slf
|
||||
}
|
||||
|
||||
// Merge 合并多个 Map
|
||||
func (slf Map[K, V]) Merge(maps ...map[K]V) Map[K, V] {
|
||||
for _, m := range maps {
|
||||
for k, v := range m {
|
||||
slf[k] = v
|
||||
}
|
||||
}
|
||||
return slf
|
||||
}
|
||||
|
||||
// ToSliceStream 将当前 Map stream 转换为 Slice stream
|
||||
func (slf Map[K, V]) ToSliceStream() Slice[V] {
|
||||
return hash.ToSlice(slf)
|
||||
}
|
||||
|
||||
// ToSliceStreamWithKey 将当前 Map stream 转换为 Slice stream,key 为 Slice 的元素
|
||||
func (slf Map[K, V]) ToSliceStreamWithKey() Slice[K] {
|
||||
return hash.KeyToSlice(slf)
|
||||
}
|
||||
|
||||
// ToSyncMap 将当前 Map 转换为 synchronization.Map
|
||||
func (slf Map[K, V]) ToSyncMap() *synchronization.Map[K, V] {
|
||||
return synchronization.NewMap[K, V](synchronization.WithMapSource(slf))
|
||||
}
|
||||
|
||||
// ToAsyncMap 将当前 Map 转换为 asynchronous.Map
|
||||
func (slf Map[K, V]) ToAsyncMap() *asynchronous.Map[K, V] {
|
||||
return asynchronous.NewMap[K, V](asynchronous.WithMapSource(slf))
|
||||
}
|
||||
|
||||
// ToMap 将当前 Map 转换为 map
|
||||
func (slf Map[K, V]) ToMap() map[K]V {
|
||||
return slf
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package stream_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kercylan98/minotaur/utils/stream"
|
||||
)
|
||||
|
||||
func ExampleWithMap() {
|
||||
m := stream.WithMap(map[int]string{1: "a", 2: "b", 3: "c", 4: "d", 5: "d"}).Filter(func(key int, value string) bool {
|
||||
return key > 3
|
||||
})
|
||||
fmt.Println(len(m))
|
||||
|
||||
// Output:
|
||||
// 2
|
||||
}
|
||||
|
||||
func ExampleWithMapCopy() {
|
||||
m := stream.WithMapCopy(map[int]string{1: "a", 2: "b", 3: "c", 4: "d", 5: "d"}).Filter(func(key int, value string) bool {
|
||||
return key > 3
|
||||
})
|
||||
fmt.Println(len(m))
|
||||
|
||||
// Output:
|
||||
// 2
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package stream_test
|
||||
|
||||
import (
|
||||
"github.com/kercylan98/minotaur/utils/stream"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func initMap() map[int]int {
|
||||
return map[int]int{
|
||||
1: 100,
|
||||
2: 200,
|
||||
3: 300,
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithMap(t *testing.T) {
|
||||
Convey("TestWithMap", t, func() {
|
||||
var s = initMap()
|
||||
var m = stream.WithMap(s).RandomDelete(1)
|
||||
So(m, ShouldNotBeNil)
|
||||
So(len(s), ShouldEqual, 2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestWithMapCopy(t *testing.T) {
|
||||
Convey("TestWithMapCopy", t, func() {
|
||||
var s = initMap()
|
||||
var m = stream.WithMapCopy(s).RandomDelete(1)
|
||||
So(m, ShouldNotBeNil)
|
||||
So(len(s), ShouldEqual, 3)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMap_Set(t *testing.T) {
|
||||
Convey("TestMap_Set", t, func() {
|
||||
var m = stream.WithMap(initMap()).Set(4, 400)
|
||||
So(m[4], ShouldEqual, 400)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMap_Filter(t *testing.T) {
|
||||
Convey("TestMap_Filter", t, func() {
|
||||
var m = stream.WithMap(initMap()).Filter(func(key int, value int) bool {
|
||||
return key == 1
|
||||
})
|
||||
So(len(m), ShouldEqual, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMap_FilterKey(t *testing.T) {
|
||||
Convey("TestMap_FilterKey", t, func() {
|
||||
var m = stream.WithMap(initMap()).FilterKey(1)
|
||||
So(len(m), ShouldEqual, 2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMap_FilterValue(t *testing.T) {
|
||||
Convey("TestMap_FilterValue", t, func() {
|
||||
var m = stream.WithMap(initMap()).FilterValue(100)
|
||||
So(len(m), ShouldEqual, 2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMap_RandomKeep(t *testing.T) {
|
||||
Convey("TestMap_RandomKeep", t, func() {
|
||||
var m = stream.WithMap(initMap()).RandomKeep(1)
|
||||
So(len(m), ShouldEqual, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMap_RandomDelete(t *testing.T) {
|
||||
Convey("TestMap_RandomDelete", t, func() {
|
||||
var m = stream.WithMap(initMap()).RandomDelete(1)
|
||||
So(len(m), ShouldEqual, 2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMap_Distinct(t *testing.T) {
|
||||
Convey("TestMap_Distinct", t, func() {
|
||||
var m = stream.WithMap(map[int]int{
|
||||
1: 100,
|
||||
2: 200,
|
||||
3: 100,
|
||||
}).Distinct(func(key int, value int) bool {
|
||||
return value == 100
|
||||
})
|
||||
So(len(m), ShouldEqual, 1)
|
||||
})
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
package stream
|
||||
|
||||
import (
|
||||
"github.com/kercylan98/minotaur/utils/hash"
|
||||
"github.com/kercylan98/minotaur/utils/slice"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// WithSlice 创建一个 Slice
|
||||
// - 该函数不会影响到传入的 slice
|
||||
func WithSlice[V any](values []V) Slice[V] {
|
||||
return slice.Copy(values)
|
||||
}
|
||||
|
||||
// Slice 提供了 slice 的链式操作
|
||||
type Slice[V any] []V
|
||||
|
||||
// Filter 过滤 handle 返回 false 的元素
|
||||
func (slf Slice[V]) Filter(handle func(index int, value V) bool) Slice[V] {
|
||||
var ns = make([]V, 0, len(slf))
|
||||
for i, v := range slf {
|
||||
if handle(i, v) {
|
||||
ns = append(ns, v)
|
||||
}
|
||||
}
|
||||
return ns
|
||||
}
|
||||
|
||||
// FilterValue 过滤特定的 value
|
||||
func (slf Slice[V]) FilterValue(values ...V) Slice[V] {
|
||||
return slf.Filter(func(index int, value V) bool {
|
||||
for _, v := range values {
|
||||
if reflect.DeepEqual(v, value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// FilterIndex 过滤特定的 index
|
||||
func (slf Slice[V]) FilterIndex(indexes ...int) Slice[V] {
|
||||
return slf.Filter(func(index int, value V) bool {
|
||||
return !slice.Contains(indexes, index)
|
||||
})
|
||||
}
|
||||
|
||||
// RandomKeep 随机保留 n 个元素
|
||||
func (slf Slice[V]) RandomKeep(n int) Slice[V] {
|
||||
length := len(slf)
|
||||
if n >= length {
|
||||
return slf
|
||||
}
|
||||
var hit = make([]int, length, length)
|
||||
for i := 0; i < n; i++ {
|
||||
hit[i] = 1
|
||||
}
|
||||
slice.Shuffle(hit)
|
||||
var ns = make([]V, 0, n)
|
||||
for i, v := range slf {
|
||||
if hit[i] == 1 {
|
||||
ns = append(ns, v)
|
||||
}
|
||||
}
|
||||
return ns
|
||||
}
|
||||
|
||||
// RandomDelete 随机删除 n 个元素
|
||||
func (slf Slice[V]) RandomDelete(n int) Slice[V] {
|
||||
length := len(slf)
|
||||
if n >= length {
|
||||
return slf[:0]
|
||||
}
|
||||
var hit = make([]int, length, length)
|
||||
for i := 0; i < n; i++ {
|
||||
hit[i] = 1
|
||||
}
|
||||
slice.Shuffle(hit)
|
||||
var ns = make([]V, 0, n)
|
||||
for i, v := range slf {
|
||||
if hit[i] == 0 {
|
||||
ns = append(ns, v)
|
||||
}
|
||||
}
|
||||
return ns
|
||||
}
|
||||
|
||||
// Shuffle 随机打乱
|
||||
func (slf Slice[V]) Shuffle() Slice[V] {
|
||||
slice.Shuffle(slf)
|
||||
return slf
|
||||
}
|
||||
|
||||
// Reverse 反转
|
||||
func (slf Slice[V]) Reverse() Slice[V] {
|
||||
slice.Reverse(slf)
|
||||
return slf
|
||||
}
|
||||
|
||||
// Clear 清空
|
||||
func (slf Slice[V]) Clear() Slice[V] {
|
||||
return slf[:0]
|
||||
}
|
||||
|
||||
// Distinct 去重,如果 handle 返回 true 则认为是重复元素
|
||||
func (slf Slice[V]) Distinct() Slice[V] {
|
||||
return slice.Distinct(slf)
|
||||
}
|
||||
|
||||
// Merge 合并
|
||||
func (slf Slice[V]) Merge(values ...V) Slice[V] {
|
||||
return append(slf, values...)
|
||||
}
|
||||
|
||||
// GetStartPart 获取前 n 个元素
|
||||
func (slf Slice[V]) GetStartPart(n int) Slice[V] {
|
||||
return slf[:n]
|
||||
}
|
||||
|
||||
// GetEndPart 获取后 n 个元素
|
||||
func (slf Slice[V]) GetEndPart(n int) Slice[V] {
|
||||
return slice.GetEndPart(slf, n)
|
||||
}
|
||||
|
||||
// GetPart 获取指定区间的元素
|
||||
func (slf Slice[V]) GetPart(start, end int) Slice[V] {
|
||||
return slice.GetPart(slf, start, end)
|
||||
}
|
||||
|
||||
// ContainsHandle 如果包含指定的元素则执行 handle
|
||||
func (slf Slice[V]) ContainsHandle(value V, handle func(slice Slice[V]) Slice[V]) Slice[V] {
|
||||
if slice.ContainsAny(slf, value) {
|
||||
return handle(slf)
|
||||
}
|
||||
return slf
|
||||
}
|
||||
|
||||
// Set 设置指定位置的元素
|
||||
func (slf Slice[V]) Set(index int, value V) Slice[V] {
|
||||
slf[index] = value
|
||||
return slf
|
||||
}
|
||||
|
||||
// Delete 删除指定位置的元素
|
||||
func (slf Slice[V]) Delete(index int) Slice[V] {
|
||||
return append(slf, slf[index+1:]...)
|
||||
}
|
||||
|
||||
// ToMapStream 将当前的 Slice stream 转换为 Map stream
|
||||
func (slf Slice[V]) ToMapStream() Map[int, V] {
|
||||
return hash.ToMap(slf)
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package stream_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kercylan98/minotaur/utils/stream"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSlice_Filter(t *testing.T) {
|
||||
Convey("TestSlice_Filter", t, func() {
|
||||
d := []int{1, 2, 3, 4, 5}
|
||||
var s = stream.WithSlice(d).Reverse()
|
||||
fmt.Println(s)
|
||||
fmt.Println(d)
|
||||
So(len(s), ShouldEqual, 2)
|
||||
})
|
||||
}
|
|
@ -6,10 +6,14 @@ import (
|
|||
"sync"
|
||||
)
|
||||
|
||||
func NewMap[Key comparable, value any]() *Map[Key, value] {
|
||||
return &Map[Key, value]{
|
||||
func NewMap[Key comparable, value any](options ...MapOption[Key, value]) *Map[Key, value] {
|
||||
m := &Map[Key, value]{
|
||||
data: make(map[Key]value),
|
||||
}
|
||||
for _, option := range options {
|
||||
option(m)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Map 并发安全的字典数据结构
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package synchronization
|
||||
|
||||
type MapOption[Key comparable, Value any] func(m *Map[Key, Value])
|
||||
|
||||
// WithMapSource 通过传入的 map 初始化
|
||||
func WithMapSource[Key comparable, Value any](source map[Key]Value) MapOption[Key, Value] {
|
||||
return func(m *Map[Key, Value]) {
|
||||
m.data = source
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue