mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-04 12:52:28 +08:00
feat: add Stream package
This commit is contained in:
75
stream/stream.go
Normal file
75
stream/stream.go
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2023 dudaodong@gmail.com. All rights resulterved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package stream implements a sequence of elements supporting sequential and parallel aggregate operations.
|
||||
// this package is a experiment to explore if stream in go can work as the way java does. it's complete, but not
|
||||
// powerful like other libs
|
||||
package stream
|
||||
|
||||
import "golang.org/x/exp/constraints"
|
||||
|
||||
// A stream should implements methods:
|
||||
// type StreamI[T any] interface {
|
||||
|
||||
// // part methods of Java Stream Specification.
|
||||
// Distinct() StreamI[T]
|
||||
// Filter(predicate func(item T) bool) StreamI[T]
|
||||
// FlatMap(mapper func(item T) StreamI[T]) StreamI[T]
|
||||
// Map(mapper func(item T) T) StreamI[T]
|
||||
// Peek(consumer func(item T)) StreamI[T]
|
||||
|
||||
// Sort(less func(a, b T) bool) StreamI[T]
|
||||
// Max(less func(a, b T) bool) (T, bool)
|
||||
// Min(less func(a, b T) bool) (T, bool)
|
||||
|
||||
// Limit(maxSize int) StreamI[T]
|
||||
// Skip(n int64) StreamI[T]
|
||||
|
||||
// AllMatch(predicate func(item T) bool) bool
|
||||
// AnyMatch(predicate func(item T) bool) bool
|
||||
// NoneMatch(predicate func(item T) bool) bool
|
||||
// ForEach(consumer func(item T))
|
||||
// Reduce(accumulator func(a, b T) T) (T, bool)
|
||||
// Count() int
|
||||
|
||||
// FindFirst() (T, bool)
|
||||
|
||||
// ToSlice() []T
|
||||
|
||||
// // part of methods custom extension
|
||||
// Reverse() StreamI[T]
|
||||
// Range(start, end int64) StreamI[T]
|
||||
// Concat(streams ...StreamI[T]) StreamI[T]
|
||||
// }
|
||||
|
||||
type stream[T any] struct {
|
||||
source []T
|
||||
}
|
||||
|
||||
// FromSlice create stream from slice.
|
||||
func FromSlice[T any](source []T) stream[T] {
|
||||
return stream[T]{source: source}
|
||||
}
|
||||
|
||||
// FromRange create a number stream from start to end. both start and end are included. [start, end]
|
||||
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T] {
|
||||
if end < start {
|
||||
panic("stream.FromRange: param start should be before param end")
|
||||
} else if step <= 0 {
|
||||
panic("stream.FromRange: param step should be positive")
|
||||
}
|
||||
|
||||
l := int((end-start)/step) + 1
|
||||
source := make([]T, l, l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
source[i] = start + (T(i) * step)
|
||||
}
|
||||
|
||||
return stream[T]{source: source}
|
||||
}
|
||||
|
||||
// ToSlice return the elements in the stream.
|
||||
func (s stream[T]) ToSlice() []T {
|
||||
return s.source
|
||||
}
|
||||
25
stream/stream_test.go
Normal file
25
stream/stream_test.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package stream
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestFromSlice(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFromSlice")
|
||||
|
||||
stream := FromSlice([]int{1, 2, 3})
|
||||
|
||||
assert.Equal([]int{1, 2, 3}, stream.ToSlice())
|
||||
}
|
||||
|
||||
func TestFromRange(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFromSlice")
|
||||
|
||||
s1 := FromRange(1, 5, 1)
|
||||
s2 := FromRange(1.1, 5.0, 1.0)
|
||||
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, s1.ToSlice())
|
||||
assert.Equal([]float64{1.1, 2.1, 3.1, 4.1}, s2.ToSlice())
|
||||
}
|
||||
Reference in New Issue
Block a user