Skip to content

Commit

Permalink
ref
Browse files Browse the repository at this point in the history
  • Loading branch information
enetx committed Apr 13, 2024
1 parent e8cbdc1 commit 0922fa4
Show file tree
Hide file tree
Showing 12 changed files with 178 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func main() {
}()

// Convert the channel into an iterator and apply filtering and mapping operations.
g.FromChannel(ch).
g.FromChan(ch).
Filter(f.Even). // Filter even numbers
Map(func(i int) int { return i * 2 }). // Double each element
Collect(). // Collect the results into a slice
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func main() {
jobs := g.SliceOf(1, 1, 1, 3, 4, 4, 8, 8, 9, 9).
Iter().
// Dedup().
ToChannel(ctx)
ToChan(ctx)

// for job := range jobs {
// fmt.Printf("job: %v\n", job)
Expand Down
19 changes: 17 additions & 2 deletions map.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package g
import (
"fmt"
"maps"
"reflect"

"github.com/enetx/g/f"
)

// NewMap creates a new Map of the specified size or an empty Map if no size is provided.
Expand Down Expand Up @@ -86,7 +87,21 @@ func (m Map[K, V]) Std() map[K]V { return m }

// Eq checks if two Maps are equal.
func (m Map[K, V]) Eq(other Map[K, V]) bool {
return maps.EqualFunc(m, other, func(x, y V) bool { return reflect.DeepEqual(x, y) })
if len(m) != len(other) || m.Empty() {
return false
}

key := m.Iter().Take(1).Keys().Collect()[0]
comparable := f.Comparable(key) && f.Comparable(m[key])

for k, v1 := range m {
v2, ok := other[k]
if !ok || (comparable && !f.Eq[any](v1)(v2)) || (!comparable && !f.Eqd(v1)(v2)) {
return false
}
}

return true
}

// String returns a string representation of the Map.
Expand Down
22 changes: 18 additions & 4 deletions map_ordered.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package g

import (
"fmt"
"reflect"
"sort"

"github.com/enetx/g/f"
)

// NewMapOrd creates a new ordered Map with the specified size (if provided).
Expand Down Expand Up @@ -241,8 +242,18 @@ func (mo MapOrd[K, V]) Invert() MapOrd[V, K] {
}

func (mo MapOrd[K, V]) index(key K) int {
if f.Comparable(key) {
for i, mp := range mo {
if f.Eq[any](mp.Key)(key) {
return i
}
}

return -1
}

for i, mp := range mo {
if reflect.DeepEqual(mp.Key, key) {
if f.Eqd(mp.Key)(key) {
return i
}
}
Expand All @@ -269,13 +280,16 @@ func (mo *MapOrd[K, V]) Delete(keys ...K) MapOrd[K, V] {

// Eq compares the current ordered Map to another ordered Map and returns true if they are equal.
func (mo MapOrd[K, V]) Eq(other MapOrd[K, V]) bool {
if len(mo) != len(other) {
if len(mo) != len(other) || mo.Empty() {
return false
}

comparable := f.Comparable(mo[0].Value)

for _, mp := range mo {
value := other.Get(mp.Key)
if value.IsNone() || !reflect.DeepEqual(value.Some(), mp.Value) {
if value.IsNone() || (comparable && !f.Eq[any](value.Some())(mp.Value)) ||
(!comparable && !f.Eqd(value.Some())(mp.Value)) {
return false
}
}
Expand Down
6 changes: 3 additions & 3 deletions map_ordered_iter.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ func (seq SeqMapOrd[K, V]) Range(fn func(k K, v V) bool) {
// The function creates a new iterator containing the first n elements from the original iterator.
func (seq SeqMapOrd[K, V]) Take(limit uint) SeqMapOrd[K, V] { return takeMapOrd(seq, limit) }

// ToChannel converts the iterator into a channel, optionally with context(s).
// ToChan converts the iterator into a channel, optionally with context(s).
//
// The function converts the key-value pairs from the iterator into a channel, allowing iterative processing
// using channels. It can be used to stream key-value pairs for concurrent or asynchronous operations.
Expand All @@ -384,13 +384,13 @@ func (seq SeqMapOrd[K, V]) Take(limit uint) SeqMapOrd[K, V] { return takeMapOrd(
// ctx, cancel := context.WithCancel(context.Background())
// defer cancel() // Ensure cancellation to avoid goroutine leaks.
//
// ch := iter.ToChannel(ctx)
// ch := iter.ToChan(ctx)
// for pair := range ch {
// // Process key-value pair from the channel
// }
//
// The function converts the iterator into a channel to allow sequential or concurrent processing of key-value pairs.
func (seq SeqMapOrd[K, V]) ToChannel(ctxs ...context.Context) chan Pair[K, V] {
func (seq SeqMapOrd[K, V]) ToChan(ctxs ...context.Context) chan Pair[K, V] {
ch := make(chan Pair[K, V])

ctx := context.Background()
Expand Down
4 changes: 1 addition & 3 deletions set.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package g

import (
"fmt"
)
import "fmt"

// NewSet creates a new Set of the specified size or an empty Set if no size is provided.
func NewSet[T comparable](size ...int) Set[T] {
Expand Down
26 changes: 12 additions & 14 deletions slice_iter.go
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ func (seq SeqSlice[V]) SortBy(fn func(a, b V) bool) SeqSlice[V] { return sortbyS
// The function creates a new iterator containing the first n elements from the original iterator.
func (seq SeqSlice[V]) Take(n uint) SeqSlice[V] { return takeSlice(seq, n) }

// ToChannel converts the iterator into a channel, optionally with context(s).
// ToChan converts the iterator into a channel, optionally with context(s).
//
// The function converts the elements of the iterator into a channel for streaming purposes.
// Optionally, it accepts context(s) to handle cancellation or timeout scenarios.
Expand All @@ -589,13 +589,13 @@ func (seq SeqSlice[V]) Take(n uint) SeqSlice[V] { return takeSlice(seq, n) }
// iter := g.Slice[int]{1, 2, 3}.Iter()
// ctx, cancel := context.WithCancel(context.Background())
// defer cancel() // Ensure cancellation to avoid goroutine leaks.
// ch := iter.ToChannel(ctx)
// ch := iter.ToChan(ctx)
// for val := range ch {
// fmt.Println(val)
// }
//
// The resulting channel allows streaming elements from the iterator with optional context handling.
func (seq SeqSlice[V]) ToChannel(ctxs ...context.Context) chan V {
func (seq SeqSlice[V]) ToChan(ctxs ...context.Context) chan V {
ch := make(chan V)

ctx := context.Background()
Expand Down Expand Up @@ -696,7 +696,7 @@ func (seq SeqSlice[V]) Find(fn func(v V) bool) Option[V] { return findSlice(seq,
// The resulting iterator will yield sliding windows of elements, each containing the specified number of elements.
func (seq SeqSlice[V]) Windows(n int) SeqSlices[V] { return windows(seq, n) }

// FromChannel converts a channel into an iterator.
// FromChan converts a channel into an iterator.
//
// This function takes a channel as input and converts its elements into an iterator,
// allowing seamless integration of channels into iterator-based processing pipelines.
Expand All @@ -720,7 +720,7 @@ func (seq SeqSlice[V]) Windows(n int) SeqSlices[V] { return windows(seq, n) }
// }()
//
// // Convert the channel into an iterator and apply filtering and mapping operations.
// g.FromChannel(ch).
// g.FromChan(ch).
// Filter(func(i int) bool { return i%2 == 0 }). // Filter even numbers.
// Map(func(i int) int { return i * 2 }). // Double each element.
// Collect(). // Collect the results into a slice.
Expand All @@ -730,7 +730,7 @@ func (seq SeqSlice[V]) Windows(n int) SeqSlices[V] { return windows(seq, n) }
//
// The resulting iterator will yield elements from the provided channel, filtering out odd numbers,
// doubling each even number, and finally collecting the results into a slice.
func FromChannel[V any](ch <-chan V) SeqSlice[V] {
func FromChan[V any](ch <-chan V) SeqSlice[V] {
return func(yield func(V) bool) {
for v := range ch {
if !yield(v) {
Expand Down Expand Up @@ -842,18 +842,16 @@ func uniqueSlice[V any](seq SeqSlice[V]) SeqSlice[V] {

// works slower
// func dedupSlice[V any](seq SeqSlice[V]) SeqSlice[V] {
// var (
// current V
// equal = f.Eqd[any]
// )
// var current V

// eq := f.Eqd[any]
// if f.Comparable(current) {
// equal = f.Eq
// eq = f.Eq
// }

// return func(yield func(V) bool) {
// seq(func(v V) bool {
// if equal(current)(v) {
// if eq(current)(v) {
// return true
// }

Expand All @@ -865,11 +863,11 @@ func uniqueSlice[V any](seq SeqSlice[V]) SeqSlice[V] {

func dedupSlice[V any](seq SeqSlice[V]) SeqSlice[V] {
var current V
isComparable := f.Comparable(current)
comparable := f.Comparable(current)

return func(yield func(V) bool) {
seq(func(v V) bool {
if isComparable {
if comparable {
if f.Eq[any](current)(v) {
return true
}
Expand Down
29 changes: 29 additions & 0 deletions tests/map_benchmark_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package g_test

import (
"testing"

"github.com/enetx/g"
)

// go test -bench=. -benchmem -count=4

func genM() g.Map[g.String, int] {
mo := g.NewMap[g.String, int](10000)
for i := range 10000 {
mo.Set(g.NewInt(i).ToString(), i)
}

return mo
}

func BenchmarkMEq(b *testing.B) {
m := genM()
m2 := m.Clone()

b.ResetTimer()

for n := 0; n < b.N; n++ {
_ = m.Eq(m2)
}
}
13 changes: 13 additions & 0 deletions tests/map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,19 @@ func TestMapEq(t *testing.T) {
if map1.Eq(map4) {
t.Errorf("Test case 3 failed: Maps with different values should not be considered equal")
}

// Test case 4
map5 := g.Map[string, []int]{"a": []int{1}, "b": []int{2}, "c": []int{4}}
map6 := g.Map[string, []int]{"a": []int{1}, "b": []int{2}, "c": []int{4}}
if map5.Ne(map6) {
t.Errorf("Test case 4 failed: Equal maps should be considered equal")
}

// Test case 5
map7 := g.Map[string, []int]{"a": []int{2}, "b": []int{5}, "c": []int{4}}
if map5.Eq(map7) {
t.Errorf("Test case 5 failed: Maps with different values should not be considered equal")
}
}

func TestMapToMap(t *testing.T) {
Expand Down
47 changes: 47 additions & 0 deletions tests/mapord_benchmark_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package g_test

import (
"testing"

"github.com/enetx/g"
)

// go test -bench=. -benchmem -count=4

func genMO() g.MapOrd[g.String, int] {
mo := g.NewMapOrd[g.String, int](10000)
for i := range 10000 {
mo.Set(g.NewInt(i).ToString(), i)
}

return mo
}

func BenchmarkMoContains(b *testing.B) {
mo := genMO()
b.ResetTimer()

for n := 0; n < b.N; n++ {
_ = mo.Contains("9999")
}
}

func BenchmarkMoEq(b *testing.B) {
mo := genMO()
mo2 := mo.Clone()

b.ResetTimer()

for n := 0; n < b.N; n++ {
_ = mo.Eq(mo2)
}
}

func BenchmarkMoGet(b *testing.B) {
mo := genMO()
b.ResetTimer()

for n := 0; n < b.N; n++ {
_ = mo.Get("9999")
}
}
10 changes: 9 additions & 1 deletion tests/mapord_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,14 @@ func TestMapOrdContains(t *testing.T) {
if m.Contains(2) {
t.Errorf("Expected map not to contain the key")
}

// Test case 3: Map contains the key
m2 := g.NewMapOrd[[]int, []int]()
m2.Set([]int{0}, []int{1})

if !m2.Contains([]int{0}) {
t.Errorf("Expected map to contain the key")
}
}

func TestMapOrdValues(t *testing.T) {
Expand Down Expand Up @@ -755,7 +763,7 @@ func TestMapOrdIterToChannel(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // Ensure cancellation to avoid goroutine leaks.

ch := mo.Iter().ToChannel(ctx)
ch := mo.Iter().ToChan(ctx)

// Collect elements from the channel
collected := g.NewMapOrd[int, int]()
Expand Down

0 comments on commit 0922fa4

Please sign in to comment.