diff --git a/README.md b/README.md index 53cb917..5d455da 100644 --- a/README.md +++ b/README.md @@ -22,22 +22,22 @@ package main import ( "fmt" - - "github.com/vkumbhar94/go-streams" + + "github.com/vkumbhar94/go-streams/pkg/streams" ) func main() { - stream := streams.New(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - filtered := streams.Filter(stream, func(i int) bool { - return i%2 == 0 - }) - mapped := streams.Map(filtered, func(i int) int { - return i * 2 - }) - limited := streams.Limit(mapped, 3) - - collected := streams.Collect(limited) - fmt.Println(collected) + result := streams.New(1, 2, 3, 4, 5, 6, 7, 8, 9, 10). + Filter( + func(i int) bool { + return i%2 == 0 + }). + Map(func(i int) int { + return i * 2 + }). + Limit(3). + Collect() + fmt.Println(result) } ``` \ No newline at end of file diff --git a/go.mod b/go.mod index 45ff676..c6fb8ac 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( github.com/stretchr/testify v1.9.0 - golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f + golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 ) require ( diff --git a/go.sum b/go.sum index 1346be2..40310ea 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f h1:3CW0unweImhOzd5FmYuRsD4Y4oQFKZIjAnKbjV4WIrw= golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/comparable_stream.go b/pkg/streams/comparable_stream.go similarity index 100% rename from comparable_stream.go rename to pkg/streams/comparable_stream.go diff --git a/map.go b/pkg/streams/map.go similarity index 92% rename from map.go rename to pkg/streams/map.go index 7cd47d5..f5d1dc5 100644 --- a/map.go +++ b/pkg/streams/map.go @@ -38,7 +38,7 @@ func MNew[K comparable, V any](data map[K]V) *Stream[MapEntry[K, V]] { } } -func MKeys[K comparable, V any](data map[K]V) *Stream[K] { +func MNewKeys[K comparable, V any](data map[K]V) *Stream[K] { ch := make(chan K) return &Stream[K]{ data: ch, @@ -53,7 +53,7 @@ func MKeys[K comparable, V any](data map[K]V) *Stream[K] { } } -func MValues[K comparable, V any](data map[K]V) *Stream[V] { +func MNewValues[K comparable, V any](data map[K]V) *Stream[V] { ch := make(chan V) return &Stream[V]{ data: ch, diff --git a/map_test.go b/pkg/streams/map_test.go similarity index 96% rename from map_test.go rename to pkg/streams/map_test.go index 2b5902d..63b8005 100644 --- a/map_test.go +++ b/pkg/streams/map_test.go @@ -87,7 +87,7 @@ func TestMStreamSorted(t *testing.T) { } func TestMStreamKeys(t *testing.T) { - stream := MKeys(map[string]int64{ + stream := MNewKeys(map[string]int64{ "abc": 2, "xyz": 4, "ijk": 3, @@ -97,7 +97,7 @@ func TestMStreamKeys(t *testing.T) { } func TestMStreamValues(t *testing.T) { - stream := MValues(map[string]int64{ + stream := MNewValues(map[string]int64{ "abc": 2, "xyz": 4, "ijk": 3, @@ -161,7 +161,7 @@ func TestMStreamReduceStringKeysToString(t *testing.T) { } func TestMStreamSum(t *testing.T) { - stream := MValues(map[string]int64{ + stream := MNewValues(map[string]int64{ "abc": 2, "xyz": 4, "ijk": 3, @@ -171,7 +171,7 @@ func TestMStreamSum(t *testing.T) { } func TestMStreamCount(t *testing.T) { - stream := MValues(map[string]int64{ + stream := MNewValues(map[string]int64{ "abc": 2, "xyz": 4, "ijk": 3, diff --git a/number_stream.go b/pkg/streams/number_stream.go similarity index 100% rename from number_stream.go rename to pkg/streams/number_stream.go diff --git a/number_stream_test.go b/pkg/streams/number_stream_test.go similarity index 100% rename from number_stream_test.go rename to pkg/streams/number_stream_test.go diff --git a/ordered_stream.go b/pkg/streams/ordered_stream.go similarity index 100% rename from ordered_stream.go rename to pkg/streams/ordered_stream.go diff --git a/stream.go b/pkg/streams/stream.go similarity index 53% rename from stream.go rename to pkg/streams/stream.go index e52d90c..5f85171 100644 --- a/stream.go +++ b/pkg/streams/stream.go @@ -37,6 +37,304 @@ func New[T any](data ...T) *Stream[T] { } } +func (s *Stream[T]) Filter(filter FilterFun[T]) *Stream[T] { + ch := make(chan T) + return &Stream[T]{ + data: ch, + run: func() { + s.Run() + defer close(ch) + for t := range s.data { + if filter(t) { + ch <- t + } + } + }, + } +} + +func (s *Stream[T]) Limit(i int) *Stream[T] { + ch := make(chan T) + return &Stream[T]{ + data: ch, + run: func() { + s.Run() + func() { + defer close(ch) + for t := range s.data { + if i > 0 { + ch <- t + i-- + } else { + break + } + } + }() + + for range s.data { + } + + }, + } +} + +func (s *Stream[T]) ForEach(f func(i T)) { + s.Run() + for t := range s.data { + f(t) + } +} + +func (s *Stream[T]) AllMatch(f func(T) bool) bool { + s.Run() + for t := range s.data { + if !f(t) { + go drain(s.data) + return false + } + } + return true +} + +func (s *Stream[T]) NotAllMatch(f func(T) bool) bool { + return !s.AllMatch(f) +} + +func (s *Stream[T]) AnyMatch(f func(T) bool) bool { + s.Run() + for t := range s.data { + if f(t) { + go drain(s.data) + return true + } + } + return false +} + +func (s *Stream[T]) NoneMatch(f func(T) bool) bool { + return !AnyMatch(s, f) +} + +func (s *Stream[T]) DropWhile(f func(T) bool) *Stream[T] { + ch := make(chan T) + return &Stream[T]{ + data: ch, + run: func() { + s.Run() + defer close(ch) + dropping := true + for t := range s.data { + if dropping && f(t) { + continue + } + dropping = false + ch <- t + } + }, + } +} + +func (s *Stream[T]) TakeWhile(f func(T) bool) *Stream[T] { + ch := make(chan T) + return &Stream[T]{ + data: ch, + run: func() { + s.Run() + func() { + defer close(ch) + for t := range s.data { + if f(t) { + ch <- t + } else { + break + } + } + }() + go drain(s.data) + }, + } +} + +func (s *Stream[T]) Peek(f func(T)) *Stream[T] { + ch := make(chan T) + return &Stream[T]{ + data: ch, + run: func() { + s.Run() + defer close(ch) + for t := range s.data { + f(t) + ch <- t + } + }, + } +} + +type OrStream[T any] struct { + Stream[T] +} + +func (s *OrStream[T]) Or(or T) T { + s.Run() + for t := range s.data { + go drain(s.data) + return t + } + return or +} + +func (s *Stream[T]) FindFirst() *T { + s.Run() + for t := range s.data { + go drain(s.data) + return &t + } + return nil +} + +func (s *Stream[T]) FindFirstOr() *OrStream[T] { + s.Run() + for t := range s.data { + go drain(s.data) + ch := make(chan T) + return &OrStream[T]{ + Stream[T]{ + data: ch, + run: func() { + defer close(ch) + ch <- t + }, + ran: atomic.Bool{}, + }, + } + } + ch := make(chan T) + return &OrStream[T]{ + Stream[T]{ + data: ch, + run: func() { + defer close(ch) + }, + ran: atomic.Bool{}, + }, + } +} + +func (s *Stream[T]) Skip(n int) *Stream[T] { + ch := make(chan T) + return &Stream[T]{ + data: ch, + run: func() { + s.Run() + defer close(ch) + for t := range s.data { + if n > 0 { + n-- + continue + } + ch <- t + } + }, + } +} + +type ElseStream[T any] struct { + Stream[T] +} + +func (s *ElseStream[T]) Else(action func(t T)) { + s.Run() + for t := range s.data { + action(t) + } +} + +func (s *Stream[T]) IfAllMatch(f func(T) bool, action func(t T)) *ElseStream[T] { + s.Run() + allMatch := true + var data []T + for t := range s.data { + if allMatch && !f(t) { + allMatch = false + } + data = append(data, t) + } + if allMatch { + for _, t := range data { + action(t) + } + } + ch := make(chan T) + return &ElseStream[T]{ + Stream: Stream[T]{ + data: ch, + run: func() { + defer close(ch) + for _, t := range data { + ch <- t + } + }, + ran: atomic.Bool{}, + }, + } +} + +func (s *Stream[T]) Collect() []T { + return Reduce(s, []T{}, func(ans []T, i T) []T { + return append(ans, i) + }) +} + +type UnaryMapFun[T any] func(T) T + +func (s *Stream[T]) Map(mapper UnaryMapFun[T]) *Stream[T] { + ch := make(chan T) + return &Stream[T]{ + data: ch, + run: func() { + s.Run() + defer close(ch) + for t := range s.data { + ch <- mapper(t) + } + }, + } +} + +func (s *Stream[T]) Reduce(result T, f func(ans T, i T) T) T { + s.Run() + for t := range s.data { + result = f(result, t) + } + return result +} + +func (s *Stream[T]) Count() (cnt int64) { + s.Run() + for range s.data { + cnt++ + } + return +} + +func (s *Stream[T]) Reverse() *Stream[T] { + ch := make(chan T) + return &Stream[T]{ + data: ch, + run: func() { + s.Run() + defer close(ch) + var data []T + for t := range s.data { + data = append(data, t) + } + for i := len(data) - 1; i >= 0; i-- { + ch <- data[i] + } + }, + } +} + func Map[T, R any](s *Stream[T], mapper MapFun[T, R]) *Stream[R] { ch := make(chan R) return &Stream[R]{ diff --git a/stream_methods_test.go b/pkg/streams/stream_test.go similarity index 56% rename from stream_methods_test.go rename to pkg/streams/stream_test.go index 674977f..21caf8c 100644 --- a/stream_methods_test.go +++ b/pkg/streams/stream_test.go @@ -1,12 +1,252 @@ package streams import ( + "fmt" "reflect" "testing" "github.com/stretchr/testify/assert" ) +func TestStreamCollect(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + collected := Collect(stream) + assert.Equal(t, []int{1, 2, 3, 4, 5}, collected) +} + +func TestStreamMap(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + mapped := Map(stream, func(i int) int { + return i * 2 + }) + collected := Collect(mapped) + assert.Equal(t, []int{2, 4, 6, 8, 10}, collected) +} + +func TestStreamFilter(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + filtered := Filter(stream, func(i int) bool { + return i%2 == 0 + }) + collected := Collect(filtered) + assert.Equal(t, []int{2, 4}, collected) +} + +func TestStreamLimit(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + limited := Limit(stream, 3) + collected := Collect(limited) + assert.Equal(t, []int{1, 2, 3}, collected) +} + +func TestStreamSorted(t *testing.T) { + stream := New(5, 3, 1, 4, 2) + sorted := Sorted(stream, ASC) + collected := Collect(sorted) + assert.Equal(t, []int{1, 2, 3, 4, 5}, collected) +} +func TestStreamReverseSorted(t *testing.T) { + stream := New(5, 3, 1, 4, 2) + sorted := Sorted(stream, DESC) + collected := Collect(sorted) + assert.Equal(t, []int{5, 4, 3, 2, 1}, collected) +} + +func TestStreamReduce(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + reduced := Reduce(stream, 0, func(ans, i int) int { + return ans + i + }) + assert.Equal(t, 15, reduced) +} + +func TestStreamSum(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + sum := Sum(stream) + assert.Equal(t, 15, sum) +} +func TestFloatStreamSum(t *testing.T) { + stream := New(1.1, 2.4, 3.9, 4.4, 5.8) + sum := Sum(stream) + assert.Equal(t, 17.6, sum) +} + +func TestStreamCount(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + count := Count(stream) + assert.Equal(t, int64(5), count) +} + +func TestStreamForEach(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + var sum int + ForEach(stream, func(i int) { + sum += i + }) + assert.Equal(t, 15, sum) +} + +func TestStreamForEach2(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + ForEach(stream, func(i int) { + fmt.Println(i) + }) +} + +func TestStreamCollectToSet(t *testing.T) { + stream := New(1, 2, 3, 3, 2) + collected := CollectToSet(stream) + assert.Equal(t, map[int]struct{}{1: {}, 2: {}, 3: {}}, collected) +} + +func TestStreamDistinct(t *testing.T) { + stream := New(1, 2, 3, 3, 2) + collected := Collect(Distinct(stream)) + assert.Equal(t, []int{1, 2, 3}, collected) +} + +func TestAllMatch(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + allMatch := AllMatch(stream, func(i int) bool { + return i < 10 + }) + assert.True(t, allMatch) +} +func TestFalseAllMatch(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + allMatch := AllMatch(stream, func(i int) bool { + return i < 3 + }) + assert.False(t, allMatch) +} + +func TestNotAllMatch(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + allMatch := NotAllMatch(stream, func(i int) bool { + return i < 10 + }) + assert.False(t, allMatch) +} + +func TestAnyMatch(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + anyMatch := AnyMatch(stream, func(i int) bool { + return i == 3 + }) + assert.True(t, anyMatch) +} + +func TestNotAnyMatch(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + anyMatch := AnyMatch(stream, func(i int) bool { + return i == 10 + }) + assert.False(t, anyMatch) +} + +func TestDropWhile(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + collected := Collect(DropWhile(stream, func(i int) bool { + return i < 3 + })) + assert.Equal(t, []int{3, 4, 5}, collected) +} + +func TestTakeWhile(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + collected := Collect(TakeWhile(stream, func(i int) bool { + return i < 3 + })) + assert.Equal(t, []int{1, 2}, collected) +} + +func TestNoneMatch(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + noneMatch := NoneMatch(stream, func(i int) bool { + return i == 10 + }) + assert.True(t, noneMatch) +} + +func TestFalseNoneMatch(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + noneMatch := NoneMatch(stream, func(i int) bool { + return i == 2 + }) + assert.False(t, noneMatch) +} + +func TestPeek(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + collected := Collect(Peek(stream, func(i int) { + fmt.Println(i) + })) + assert.Equal(t, []int{1, 2, 3, 4, 5}, collected) +} + +func TestFindFirst(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + first := FindFirst(stream) + assert.Equal(t, 1, *first) +} + +func TestFindFirstEmpty(t *testing.T) { + stream := New[int]() + first := FindFirst(stream) + assert.Nil(t, first) +} + +func TestFlatmap(t *testing.T) { + stream := New([]int{1, 2, 3}, []int{4, 5}, []int{6, 7, 8, 9}) + flatMapped := FlatMap(stream, func(i []int) *Stream[int] { + return New(i...) + }) + collected := Collect(flatMapped) + assert.Equal(t, []int{1, 2, 3, 4, 5, 6, 7, 8, 9}, collected) +} + +func TestMin(t *testing.T) { + stream := New(5, 3, 1, 4, 2) + minVal := Min(stream) + assert.Equal(t, 1, *minVal) +} + +func TestMax(t *testing.T) { + stream := New(5, 3, 1, 4, 2) + maxVal := Max(stream) + assert.Equal(t, 5, *maxVal) +} + +func TestSkip(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + collected := Collect(Skip(stream, 2)) + assert.Equal(t, []int{3, 4, 5}, collected) +} + +func TestIfAllMatch(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + IfAllMatch(stream, + func(i int) bool { + return i < 10 + }, + func(t int) { + fmt.Println(t) + }, + ) +} + +func TestIfAllMatchNegativeCase(t *testing.T) { + stream := New(1, 2, 3, 4, 5) + IfAllMatch(stream, + func(i int) bool { + return i > 10 + }, + func(t int) { + fmt.Println(t) + }, + ) +} + func TestFilter(t *testing.T) { collected := New([]int{1, 2, 3, 4, 5}...).Filter(func(i int) bool { return i > 2 diff --git a/util.go b/pkg/streams/util.go similarity index 100% rename from util.go rename to pkg/streams/util.go diff --git a/stream_methods.go b/stream_methods.go deleted file mode 100644 index a382e79..0000000 --- a/stream_methods.go +++ /dev/null @@ -1,303 +0,0 @@ -package streams - -import ( - "sync/atomic" -) - -func (s *Stream[T]) Filter(filter FilterFun[T]) *Stream[T] { - ch := make(chan T) - return &Stream[T]{ - data: ch, - run: func() { - s.Run() - defer close(ch) - for t := range s.data { - if filter(t) { - ch <- t - } - } - }, - } -} - -func (s *Stream[T]) Limit(i int) *Stream[T] { - ch := make(chan T) - return &Stream[T]{ - data: ch, - run: func() { - s.Run() - func() { - defer close(ch) - for t := range s.data { - if i > 0 { - ch <- t - i-- - } else { - break - } - } - }() - - for range s.data { - } - - }, - } -} - -func (s *Stream[T]) ForEach(f func(i T)) { - s.Run() - for t := range s.data { - f(t) - } -} - -func (s *Stream[T]) AllMatch(f func(T) bool) bool { - s.Run() - for t := range s.data { - if !f(t) { - go drain(s.data) - return false - } - } - return true -} - -func (s *Stream[T]) NotAllMatch(f func(T) bool) bool { - return !s.AllMatch(f) -} - -func (s *Stream[T]) AnyMatch(f func(T) bool) bool { - s.Run() - for t := range s.data { - if f(t) { - go drain(s.data) - return true - } - } - return false -} - -func (s *Stream[T]) NoneMatch(f func(T) bool) bool { - return !AnyMatch(s, f) -} - -func (s *Stream[T]) DropWhile(f func(T) bool) *Stream[T] { - ch := make(chan T) - return &Stream[T]{ - data: ch, - run: func() { - s.Run() - defer close(ch) - dropping := true - for t := range s.data { - if dropping && f(t) { - continue - } - dropping = false - ch <- t - } - }, - } -} - -func (s *Stream[T]) TakeWhile(f func(T) bool) *Stream[T] { - ch := make(chan T) - return &Stream[T]{ - data: ch, - run: func() { - s.Run() - func() { - defer close(ch) - for t := range s.data { - if f(t) { - ch <- t - } else { - break - } - } - }() - go drain(s.data) - }, - } -} - -func (s *Stream[T]) Peek(f func(T)) *Stream[T] { - ch := make(chan T) - return &Stream[T]{ - data: ch, - run: func() { - s.Run() - defer close(ch) - for t := range s.data { - f(t) - ch <- t - } - }, - } -} - -type OrStream[T any] struct { - Stream[T] -} - -func (s *OrStream[T]) Or(or T) T { - s.Run() - for t := range s.data { - go drain(s.data) - return t - } - return or -} - -func (s *Stream[T]) FindFirst() *T { - s.Run() - for t := range s.data { - go drain(s.data) - return &t - } - return nil -} - -func (s *Stream[T]) FindFirstOr() *OrStream[T] { - s.Run() - for t := range s.data { - go drain(s.data) - ch := make(chan T) - return &OrStream[T]{ - Stream[T]{ - data: ch, - run: func() { - defer close(ch) - ch <- t - }, - ran: atomic.Bool{}, - }, - } - } - ch := make(chan T) - return &OrStream[T]{ - Stream[T]{ - data: ch, - run: func() { - defer close(ch) - }, - ran: atomic.Bool{}, - }, - } -} - -func (s *Stream[T]) Skip(n int) *Stream[T] { - ch := make(chan T) - return &Stream[T]{ - data: ch, - run: func() { - s.Run() - defer close(ch) - for t := range s.data { - if n > 0 { - n-- - continue - } - ch <- t - } - }, - } -} - -type ElseStream[T any] struct { - Stream[T] -} - -func (s *ElseStream[T]) Else(action func(t T)) { - s.Run() - for t := range s.data { - action(t) - } -} - -func (s *Stream[T]) IfAllMatch(f func(T) bool, action func(t T)) *ElseStream[T] { - s.Run() - allMatch := true - var data []T - for t := range s.data { - if allMatch && !f(t) { - allMatch = false - } - data = append(data, t) - } - if allMatch { - for _, t := range data { - action(t) - } - } - ch := make(chan T) - return &ElseStream[T]{ - Stream: Stream[T]{ - data: ch, - run: func() { - defer close(ch) - for _, t := range data { - ch <- t - } - }, - ran: atomic.Bool{}, - }, - } -} - -func (s *Stream[T]) Collect() []T { - return Reduce(s, []T{}, func(ans []T, i T) []T { - return append(ans, i) - }) -} - -type UnaryMapFun[T any] func(T) T - -func (s *Stream[T]) Map(mapper UnaryMapFun[T]) *Stream[T] { - ch := make(chan T) - return &Stream[T]{ - data: ch, - run: func() { - s.Run() - defer close(ch) - for t := range s.data { - ch <- mapper(t) - } - }, - } -} - -func (s *Stream[T]) Reduce(result T, f func(ans T, i T) T) T { - s.Run() - for t := range s.data { - result = f(result, t) - } - return result -} - -func (s *Stream[T]) Count() (cnt int64) { - s.Run() - for range s.data { - cnt++ - } - return -} - -func (s *Stream[T]) Reverse() *Stream[T] { - ch := make(chan T) - return &Stream[T]{ - data: ch, - run: func() { - s.Run() - defer close(ch) - var data []T - for t := range s.data { - data = append(data, t) - } - for i := len(data) - 1; i >= 0; i-- { - ch <- data[i] - } - }, - } -} diff --git a/stream_test.go b/stream_test.go deleted file mode 100644 index f8863d0..0000000 --- a/stream_test.go +++ /dev/null @@ -1,247 +0,0 @@ -package streams - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestStreamCollect(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - collected := Collect(stream) - assert.Equal(t, []int{1, 2, 3, 4, 5}, collected) -} - -func TestStreamMap(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - mapped := Map(stream, func(i int) int { - return i * 2 - }) - collected := Collect(mapped) - assert.Equal(t, []int{2, 4, 6, 8, 10}, collected) -} - -func TestStreamFilter(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - filtered := Filter(stream, func(i int) bool { - return i%2 == 0 - }) - collected := Collect(filtered) - assert.Equal(t, []int{2, 4}, collected) -} - -func TestStreamLimit(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - limited := Limit(stream, 3) - collected := Collect(limited) - assert.Equal(t, []int{1, 2, 3}, collected) -} - -func TestStreamSorted(t *testing.T) { - stream := New(5, 3, 1, 4, 2) - sorted := Sorted(stream, ASC) - collected := Collect(sorted) - assert.Equal(t, []int{1, 2, 3, 4, 5}, collected) -} -func TestStreamReverseSorted(t *testing.T) { - stream := New(5, 3, 1, 4, 2) - sorted := Sorted(stream, DESC) - collected := Collect(sorted) - assert.Equal(t, []int{5, 4, 3, 2, 1}, collected) -} - -func TestStreamReduce(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - reduced := Reduce(stream, 0, func(ans, i int) int { - return ans + i - }) - assert.Equal(t, 15, reduced) -} - -func TestStreamSum(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - sum := Sum(stream) - assert.Equal(t, 15, sum) -} -func TestFloatStreamSum(t *testing.T) { - stream := New(1.1, 2.4, 3.9, 4.4, 5.8) - sum := Sum(stream) - assert.Equal(t, 17.6, sum) -} - -func TestStreamCount(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - count := Count(stream) - assert.Equal(t, int64(5), count) -} - -func TestStreamForEach(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - var sum int - ForEach(stream, func(i int) { - sum += i - }) - assert.Equal(t, 15, sum) -} - -func TestStreamForEach2(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - ForEach(stream, func(i int) { - fmt.Println(i) - }) -} - -func TestStreamCollectToSet(t *testing.T) { - stream := New(1, 2, 3, 3, 2) - collected := CollectToSet(stream) - assert.Equal(t, map[int]struct{}{1: {}, 2: {}, 3: {}}, collected) -} - -func TestStreamDistinct(t *testing.T) { - stream := New(1, 2, 3, 3, 2) - collected := Collect(Distinct(stream)) - assert.Equal(t, []int{1, 2, 3}, collected) -} - -func TestAllMatch(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - allMatch := AllMatch(stream, func(i int) bool { - return i < 10 - }) - assert.True(t, allMatch) -} -func TestFalseAllMatch(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - allMatch := AllMatch(stream, func(i int) bool { - return i < 3 - }) - assert.False(t, allMatch) -} - -func TestNotAllMatch(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - allMatch := NotAllMatch(stream, func(i int) bool { - return i < 10 - }) - assert.False(t, allMatch) -} - -func TestAnyMatch(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - anyMatch := AnyMatch(stream, func(i int) bool { - return i == 3 - }) - assert.True(t, anyMatch) -} - -func TestNotAnyMatch(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - anyMatch := AnyMatch(stream, func(i int) bool { - return i == 10 - }) - assert.False(t, anyMatch) -} - -func TestDropWhile(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - collected := Collect(DropWhile(stream, func(i int) bool { - return i < 3 - })) - assert.Equal(t, []int{3, 4, 5}, collected) -} - -func TestTakeWhile(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - collected := Collect(TakeWhile(stream, func(i int) bool { - return i < 3 - })) - assert.Equal(t, []int{1, 2}, collected) -} - -func TestNoneMatch(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - noneMatch := NoneMatch(stream, func(i int) bool { - return i == 10 - }) - assert.True(t, noneMatch) -} - -func TestFalseNoneMatch(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - noneMatch := NoneMatch(stream, func(i int) bool { - return i == 2 - }) - assert.False(t, noneMatch) -} - -func TestPeek(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - collected := Collect(Peek(stream, func(i int) { - fmt.Println(i) - })) - assert.Equal(t, []int{1, 2, 3, 4, 5}, collected) -} - -func TestFindFirst(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - first := FindFirst(stream) - assert.Equal(t, 1, *first) -} - -func TestFindFirstEmpty(t *testing.T) { - stream := New[int]() - first := FindFirst(stream) - assert.Nil(t, first) -} - -func TestFlatmap(t *testing.T) { - stream := New([]int{1, 2, 3}, []int{4, 5}, []int{6, 7, 8, 9}) - flatMapped := FlatMap(stream, func(i []int) *Stream[int] { - return New(i...) - }) - collected := Collect(flatMapped) - assert.Equal(t, []int{1, 2, 3, 4, 5, 6, 7, 8, 9}, collected) -} - -func TestMin(t *testing.T) { - stream := New(5, 3, 1, 4, 2) - minVal := Min(stream) - assert.Equal(t, 1, *minVal) -} - -func TestMax(t *testing.T) { - stream := New(5, 3, 1, 4, 2) - maxVal := Max(stream) - assert.Equal(t, 5, *maxVal) -} - -func TestSkip(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - collected := Collect(Skip(stream, 2)) - assert.Equal(t, []int{3, 4, 5}, collected) -} - -func TestIfAllMatch(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - IfAllMatch(stream, - func(i int) bool { - return i < 10 - }, - func(t int) { - fmt.Println(t) - }, - ) -} - -func TestIfAllMatchNegativeCase(t *testing.T) { - stream := New(1, 2, 3, 4, 5) - IfAllMatch(stream, - func(i int) bool { - return i > 10 - }, - func(t int) { - fmt.Println(t) - }, - ) -}