diff --git a/pkg/xmap/README.md b/pkg/xmap/README.md index 06cbf93..5e6e50d 100644 --- a/pkg/xmap/README.md +++ b/pkg/xmap/README.md @@ -14,10 +14,15 @@ import "github.com/dashjay/xiter/pkg/xmap" - [func Equal\[M1, M2 \~map\[K\]V, K, V comparable\]\(m1 M1, m2 M2\) bool](<#Equal>) - [func EqualFunc\[M1 \~map\[K\]V1, M2 \~map\[K\]V2, K comparable, V1, V2 any\]\(m1 M1, m2 M2, eq func\(V1, V2\) bool\) bool](<#EqualFunc>) - [func Filter\[M \~map\[K\]V, K comparable, V any\]\(in M, fn func\(K, V\) bool\) M](<#Filter>) +- [func Find\[K comparable, V any\]\(in map\[K\]V, fn func\(K, V\) bool\) \(K, V, bool\)](<#Find>) +- [func FindKey\[K comparable, V any\]\(in map\[K\]V, target K\) \(K, V, bool\)](<#FindKey>) +- [func FindKeyO\[K comparable, V any\]\(in map\[K\]V, target K\) optional.O\[union.U2\[K, V\]\]](<#FindKeyO>) +- [func FindO\[K comparable, V any\]\(in map\[K\]V, fn func\(K, V\) bool\) optional.O\[union.U2\[K, V\]\]](<#FindO>) - [func Keys\[M \~map\[K\]V, K comparable, V any\]\(m M\) \[\]K](<#Keys>) - [func MapKeys\[K comparable, V1 any\]\(in map\[K\]V1, fn func\(K, V1\) K\) map\[K\]V1](<#MapKeys>) - [func MapValues\[K comparable, V1, V2 any\]\(in map\[K\]V1, fn func\(K, V1\) V2\) map\[K\]V2](<#MapValues>) - [func ToUnionSlice\[M \~map\[K\]V, K comparable, V any\]\(m M\) \[\]union.U2\[K, V\]](<#ToUnionSlice>) +- [func ToXSyncMap\[K comparable, V any\]\(in map\[K\]V\) \*xsync.SyncMap\[K, V\]](<#ToXSyncMap>) - [func Values\[M \~map\[K\]V, K comparable, V any\]\(m M\) \[\]V](<#Values>) @@ -31,7 +36,7 @@ func Clone[M ~map[K]V, K comparable, V any](m M) M -## func [CoalesceMaps]() +## func [CoalesceMaps]() ```go func CoalesceMaps[M ~map[K]V, K comparable, V any](maps ...M) M @@ -93,7 +98,7 @@ func EqualFunc[M1 ~map[K]V1, M2 ~map[K]V2, K comparable, V1, V2 any](m1 M1, m2 M -## func [Filter]() +## func [Filter]() ```go func Filter[M ~map[K]V, K comparable, V any](in M, fn func(K, V) bool) M @@ -110,6 +115,42 @@ result := Filter(m, fn) // result will be map[string]int{"b": 2, "c": 3} ``` + +## func [Find]() + +```go +func Find[K comparable, V any](in map[K]V, fn func(K, V) bool) (K, V, bool) +``` + + + + +## func [FindKey]() + +```go +func FindKey[K comparable, V any](in map[K]V, target K) (K, V, bool) +``` + + + + +## func [FindKeyO]() + +```go +func FindKeyO[K comparable, V any](in map[K]V, target K) optional.O[union.U2[K, V]] +``` + + + + +## func [FindO]() + +```go +func FindO[K comparable, V any](in map[K]V, fn func(K, V) bool) optional.O[union.U2[K, V]] +``` + + + ## func [Keys]() @@ -120,7 +161,7 @@ func Keys[M ~map[K]V, K comparable, V any](m M) []K -## func [MapKeys]() +## func [MapKeys]() ```go func MapKeys[K comparable, V1 any](in map[K]V1, fn func(K, V1) K) map[K]V1 @@ -153,7 +194,7 @@ result := MapKeys(m, fn) ``` -## func [MapValues]() +## func [MapValues]() ```go func MapValues[K comparable, V1, V2 any](in map[K]V1, fn func(K, V1) V2) map[K]V2 @@ -194,6 +235,27 @@ func ToUnionSlice[M ~map[K]V, K comparable, V any](m M) []union.U2[K, V] + +## func [ToXSyncMap]() + +```go +func ToXSyncMap[K comparable, V any](in map[K]V) *xsync.SyncMap[K, V] +``` + +ToXSyncMap converts a map to a xsync.SyncMap. + +Parameters: + +``` +in map[K]V: The input map to convert +``` + +Returns: + +``` +*xsync.SyncMap[K, V]: A new xsync.SyncMap containing the same key-value pairs as the input map +``` + ## func [Values]() diff --git a/pkg/xmap/xmap_common.go b/pkg/xmap/xmap_common.go index 9798227..5519407 100644 --- a/pkg/xmap/xmap_common.go +++ b/pkg/xmap/xmap_common.go @@ -1,7 +1,10 @@ package xmap import ( + "github.com/dashjay/xiter/pkg/optional" + "github.com/dashjay/xiter/pkg/union" "github.com/dashjay/xiter/pkg/xiter" + "github.com/dashjay/xiter/pkg/xsync" ) // CoalesceMaps combines multiple maps into a single map. When duplicate keys are encountered, @@ -96,3 +99,57 @@ func MapValues[K comparable, V1, V2 any](in map[K]V1, fn func(K, V1) V2) map[K]V func MapKeys[K comparable, V1 any](in map[K]V1, fn func(K, V1) K) map[K]V1 { return xiter.ToMap(xiter.Map2(func(k K, v V1) (K, V1) { return fn(k, v), v }, xiter.FromMapKeyAndValues(in))) } + +// ToXSyncMap converts a map to a xsync.SyncMap. +// +// Parameters: +// +// in map[K]V: The input map to convert +// +// Returns: +// +// *xsync.SyncMap[K, V]: A new xsync.SyncMap containing the same key-value pairs as the input map +func ToXSyncMap[K comparable, V any](in map[K]V) *xsync.SyncMap[K, V] { + m := xsync.NewSyncMap[K, V]() + for k, v := range in { + m.Store(k, v) + } + return m +} + +func FindKey[K comparable, V any](in map[K]V, target K) (K, V, bool) { + v, ok := in[target] + if ok { + return target, v, ok + } + var zero K + return zero, v, ok +} + +func FindKeyO[K comparable, V any](in map[K]V, target K) optional.O[union.U2[K, V]] { + v, ok := in[target] + if ok { + return optional.FromValue(union.U2[K, V]{T1: target, T2: v}) + } + return optional.Empty[union.U2[K, V]]() +} + +func Find[K comparable, V any](in map[K]V, fn func(K, V) bool) (K, V, bool) { + for k, v := range in { + if fn(k, v) { + return k, v, true + } + } + var k K + var v V + return k, v, false +} + +func FindO[K comparable, V any](in map[K]V, fn func(K, V) bool) optional.O[union.U2[K, V]] { + for k, v := range in { + if fn(k, v) { + return optional.FromValue(union.U2[K, V]{T1: k, T2: v}) + } + } + return optional.Empty[union.U2[K, V]]() +} diff --git a/pkg/xmap/xmap_test.go b/pkg/xmap/xmap_test.go index a5bcd6c..1c43a47 100644 --- a/pkg/xmap/xmap_test.go +++ b/pkg/xmap/xmap_test.go @@ -132,7 +132,52 @@ func TestMap(t *testing.T) { emptyMap := map[string]int{} emptyResult := xmap.MapKeys(emptyMap, fn) assert.Equal(t, map[string]int{}, emptyResult) - }) + t.Run("to xsync-map", func(t *testing.T) { + m := xmap.ToXSyncMap(_map(0, 100)) + assert.Equal(t, 100, m.Len()) + }) + + t.Run("xmap find", func(t *testing.T) { + k, _, ok := xmap.Find(_map(0, 100), func(k int, v string) bool { + return k == 50 + }) + assert.Equal(t, 50, k) + assert.True(t, ok) + + res := xmap.FindO(_map(0, 100), func(k int, v string) bool { + return k == 50 + }) + assert.Equal(t, 50, res.Must().T1) + assert.True(t, res.Ok()) + + k, _, ok = xmap.FindKey(_map(0, 100), 50) + assert.Equal(t, 50, k) + assert.True(t, ok) + + res = xmap.FindKeyO(_map(0, 100), 50) + assert.Equal(t, 50, res.Must().T1) + assert.True(t, res.Ok()) + + // can not find + k, _, ok = xmap.Find(_map(0, 100), func(k int, v string) bool { + return k == 100 + }) + assert.Equal(t, 0, k) + assert.False(t, ok) + + res = xmap.FindO(_map(0, 100), func(k int, v string) bool { + return k == 100 + }) + assert.False(t, res.Ok()) + + k, _, ok = xmap.FindKey(_map(0, 100), 100) + assert.Equal(t, 0, k) + assert.False(t, ok) + + res = xmap.FindKeyO(_map(0, 100), 100) + assert.False(t, res.Ok()) + + }) }