mirror of
https://github.com/duke-git/lancet.git
synced 2026-03-01 00:35:28 +08:00
Compare commits
6
Commits
22af59565e
...
874d09f331
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
874d09f331 | ||
|
|
fdf251ac98 | ||
|
|
7ec2533b7a | ||
|
|
9fd0603f4a | ||
|
|
9f7b416a8d | ||
|
|
bf4b2b5fd6 |
@@ -20,5 +20,7 @@ jobs:
|
||||
go-version: "1.18"
|
||||
- name: Run coverage
|
||||
run: go test -v ./... -coverprofile=coverage.txt -covermode=atomic
|
||||
- name: Run govet
|
||||
run: go vet -v ./...
|
||||
- name: Upload coverage to Codecov
|
||||
run: bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package optional
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Optional is a type that may or may not contain a non-nil value.
|
||||
type Optional[T any] struct {
|
||||
value *T
|
||||
mu *sync.RWMutex
|
||||
}
|
||||
|
||||
// Empty returns an empty Optional instance.
|
||||
func Empty[T any]() Optional[T] {
|
||||
return Optional[T]{mu: &sync.RWMutex{}}
|
||||
}
|
||||
|
||||
// Of returns an Optional with a non-nil value.
|
||||
func Of[T any](value T) Optional[T] {
|
||||
return Optional[T]{value: &value, mu: &sync.RWMutex{}}
|
||||
}
|
||||
|
||||
// OfNullable returns an Optional for a given value, which may be nil.
|
||||
func OfNullable[T any](value *T) Optional[T] {
|
||||
if value == nil {
|
||||
return Empty[T]()
|
||||
}
|
||||
return Optional[T]{value: value, mu: &sync.RWMutex{}}
|
||||
}
|
||||
|
||||
// IsPresent checks if there is a value present.
|
||||
func (o Optional[T]) IsPresent() bool {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
return o.value != nil
|
||||
}
|
||||
|
||||
// IsEmpty checks if the Optional is empty.
|
||||
func (o Optional[T]) IsEmpty() bool {
|
||||
return !o.IsPresent()
|
||||
}
|
||||
|
||||
// IfPresent performs the given action with the value if a value is present.
|
||||
func (o Optional[T]) IfPresent(action func(value T)) {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
if o.value != nil {
|
||||
action(*o.value)
|
||||
}
|
||||
}
|
||||
|
||||
// IfPresentOrElse performs the action with the value if present, otherwise performs the empty-based action.
|
||||
func (o Optional[T]) IfPresentOrElse(action func(value T), emptyAction func()) {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
if o.value != nil {
|
||||
action(*o.value)
|
||||
} else {
|
||||
emptyAction()
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the value if present, otherwise panics.
|
||||
func (o Optional[T]) Get() T {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
if o.value == nil {
|
||||
panic("Optional.Get: no value present")
|
||||
}
|
||||
return *o.value
|
||||
}
|
||||
|
||||
// OrElse returns the value if present, otherwise returns other.
|
||||
func (o Optional[T]) OrElse(other T) T {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
if o.value != nil {
|
||||
return *o.value
|
||||
}
|
||||
return other
|
||||
}
|
||||
|
||||
// OrElseGet returns the value if present, otherwise invokes supplier and returns the result.
|
||||
func (o Optional[T]) OrElseGet(supplier func() T) T {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
if o.value != nil {
|
||||
return *o.value
|
||||
}
|
||||
return supplier()
|
||||
}
|
||||
|
||||
// OrElseThrow returns the value if present, otherwise returns an error.
|
||||
func (o Optional[T]) OrElseThrow(errorSupplier func() error) (T, error) {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
if o.value == nil {
|
||||
return *new(T), errorSupplier()
|
||||
}
|
||||
return *o.value, nil
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package optional
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEmpty")
|
||||
opt := Empty[int]()
|
||||
|
||||
assert.ShouldBeTrue(opt.IsEmpty())
|
||||
}
|
||||
|
||||
func TestOf(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOf")
|
||||
value := 42
|
||||
opt := Of(value)
|
||||
|
||||
assert.ShouldBeTrue(opt.IsPresent())
|
||||
assert.Equal(opt.Get(), value)
|
||||
}
|
||||
|
||||
func TestOfNullable(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOfNullable")
|
||||
var value *int = nil
|
||||
opt := OfNullable(value)
|
||||
|
||||
assert.ShouldBeFalse(opt.IsPresent())
|
||||
|
||||
value = new(int)
|
||||
*value = 42
|
||||
opt = OfNullable(value)
|
||||
|
||||
assert.ShouldBeTrue(opt.IsPresent())
|
||||
}
|
||||
|
||||
func TestOrElse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOrElse")
|
||||
optEmpty := Empty[int]()
|
||||
defaultValue := 100
|
||||
|
||||
val := optEmpty.OrElse(defaultValue)
|
||||
assert.Equal(val, defaultValue)
|
||||
|
||||
optWithValue := Of(42)
|
||||
val = optWithValue.OrElse(defaultValue)
|
||||
assert.Equal(val, 42)
|
||||
}
|
||||
|
||||
func TestOrElseGetHappyPath(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOrElseGetHappyPath")
|
||||
optWithValue := Of(42)
|
||||
supplier := func() int { return 100 }
|
||||
|
||||
val := optWithValue.OrElseGet(supplier)
|
||||
assert.Equal(val, 42)
|
||||
}
|
||||
|
||||
func TestOrElseGet(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOrElseGet")
|
||||
optEmpty := Empty[int]()
|
||||
supplier := func() int { return 100 }
|
||||
|
||||
val := optEmpty.OrElseGet(supplier)
|
||||
assert.Equal(val, supplier())
|
||||
}
|
||||
|
||||
func TestOrElseThrow(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOrElseThrow")
|
||||
optEmpty := Empty[int]()
|
||||
_, err := optEmpty.OrElseThrow(func() error { return errors.New("no value") })
|
||||
|
||||
assert.Equal(err.Error(), "no value")
|
||||
|
||||
optWithValue := Of(42)
|
||||
val, err := optWithValue.OrElseThrow(func() error { return errors.New("no value") })
|
||||
|
||||
assert.IsNil(err)
|
||||
assert.Equal(val, 42)
|
||||
}
|
||||
|
||||
func TestIfPresent(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIfPresent")
|
||||
called := false
|
||||
action := func(value int) { called = true }
|
||||
|
||||
optEmpty := Empty[int]()
|
||||
optEmpty.IfPresent(action)
|
||||
|
||||
assert.ShouldBeFalse(called)
|
||||
|
||||
called = false // Reset for next test
|
||||
optWithValue := Of(42)
|
||||
optWithValue.IfPresent(action)
|
||||
|
||||
assert.ShouldBeTrue(called)
|
||||
}
|
||||
|
||||
func TestIfPresentOrElse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIfPresentOrElse")
|
||||
|
||||
// Test when value is present
|
||||
calledWithValue := false
|
||||
valueAction := func(value int) { calledWithValue = true }
|
||||
emptyAction := func() { t.Errorf("Empty action should not be called when value is present") }
|
||||
|
||||
optWithValue := Of(42)
|
||||
optWithValue.IfPresentOrElse(valueAction, emptyAction)
|
||||
|
||||
assert.ShouldBeTrue(calledWithValue)
|
||||
|
||||
// Test when value is not present
|
||||
calledWithEmpty := false
|
||||
valueAction = func(value int) { t.Errorf("Value action should not be called when value is not present") }
|
||||
emptyAction = func() { calledWithEmpty = true }
|
||||
|
||||
optEmpty := Empty[int]()
|
||||
optEmpty.IfPresentOrElse(valueAction, emptyAction)
|
||||
|
||||
assert.ShouldBeTrue(calledWithEmpty)
|
||||
}
|
||||
|
||||
func TestGetWithPanicStandard(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestGetWithPanicStandard")
|
||||
|
||||
// Test when value is present
|
||||
optWithValue := Of(42)
|
||||
func() {
|
||||
defer func() {
|
||||
r := recover()
|
||||
assert.IsNil(r)
|
||||
}()
|
||||
val := optWithValue.Get()
|
||||
if val != 42 {
|
||||
t.Errorf("Expected Get to return 42, got %v", val)
|
||||
}
|
||||
}()
|
||||
|
||||
// Test when value is not present
|
||||
optEmpty := Empty[int]()
|
||||
func() {
|
||||
defer func() {
|
||||
r := recover()
|
||||
assert.IsNotNil(r)
|
||||
}()
|
||||
_ = optEmpty.Get()
|
||||
}()
|
||||
}
|
||||
@@ -37,6 +37,20 @@ func (a *Assert) Equal(expected, actual any) {
|
||||
}
|
||||
}
|
||||
|
||||
// ShouldBeFalse check if expected is false
|
||||
func (a *Assert) ShouldBeFalse(actual any) {
|
||||
if compare(false, actual) != compareEqual {
|
||||
makeTestFailed(a.T, a.CaseName, false, actual)
|
||||
}
|
||||
}
|
||||
|
||||
// ShouldBeTrue check if expected is true
|
||||
func (a *Assert) ShouldBeTrue(actual any) {
|
||||
if compare(true, actual) != compareEqual {
|
||||
makeTestFailed(a.T, a.CaseName, true, actual)
|
||||
}
|
||||
}
|
||||
|
||||
// NotEqual check if expected is not equal with actual
|
||||
func (a *Assert) NotEqual(expected, actual any) {
|
||||
if compare(expected, actual) == compareEqual {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package maputil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
@@ -303,3 +304,79 @@ func HasKey[K comparable, V any](m map[K]V, key K) bool {
|
||||
_, haskey := m[key]
|
||||
return haskey
|
||||
}
|
||||
|
||||
// MapToStruct converts map to struct
|
||||
// Play: todo
|
||||
func MapToStruct(m map[string]interface{}, structObj interface{}) error {
|
||||
|
||||
for k, v := range m {
|
||||
err := setStructField(structObj, k, v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setStructField(structObj any, fieldName string, fieldValue any) error {
|
||||
structVal := reflect.ValueOf(structObj).Elem()
|
||||
|
||||
fName := getFieldNameByJsonTag(structObj, fieldName)
|
||||
if fName == "" {
|
||||
return fmt.Errorf("Struct field json tag don't match map key : %s in obj", fieldName)
|
||||
}
|
||||
|
||||
fieldVal := structVal.FieldByName(fName)
|
||||
|
||||
if !fieldVal.IsValid() {
|
||||
return fmt.Errorf("No such field: %s in obj", fieldName)
|
||||
}
|
||||
|
||||
if !fieldVal.CanSet() {
|
||||
return fmt.Errorf("Cannot set %s field value", fieldName)
|
||||
}
|
||||
|
||||
val := reflect.ValueOf(fieldValue)
|
||||
|
||||
if fieldVal.Type() != val.Type() {
|
||||
|
||||
if m, ok := fieldValue.(map[string]interface{}); ok {
|
||||
|
||||
if fieldVal.Kind() == reflect.Struct {
|
||||
return MapToStruct(m, fieldVal.Addr().Interface())
|
||||
}
|
||||
|
||||
if fieldVal.Kind() == reflect.Ptr && fieldVal.Type().Elem().Kind() == reflect.Struct {
|
||||
if fieldVal.IsNil() {
|
||||
fieldVal.Set(reflect.New(fieldVal.Type().Elem()))
|
||||
}
|
||||
|
||||
return MapToStruct(m, fieldVal.Interface())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return fmt.Errorf("Map value type don't match struct field type")
|
||||
}
|
||||
|
||||
fieldVal.Set(val)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getFieldNameByJsonTag(structObj any, jsonTag string) string {
|
||||
s := reflect.TypeOf(structObj).Elem()
|
||||
|
||||
for i := 0; i < s.NumField(); i++ {
|
||||
field := s.Field(i)
|
||||
tag := field.Tag
|
||||
name := tag.Get("json")
|
||||
|
||||
if name == jsonTag {
|
||||
return field.Name
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -472,3 +472,42 @@ func TestHasKey(t *testing.T) {
|
||||
assert.Equal(true, HasKey(m, "a"))
|
||||
assert.Equal(false, HasKey(m, "c"))
|
||||
}
|
||||
|
||||
func TestMapToStruct(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMapToStruct")
|
||||
|
||||
type (
|
||||
Person struct {
|
||||
Name string `json:"name"`
|
||||
Age int `json:"age"`
|
||||
Phone string `json:"phone"`
|
||||
Addr *Address `json:"address"`
|
||||
}
|
||||
|
||||
Address struct {
|
||||
Street string `json:"street"`
|
||||
Number int `json:"number"`
|
||||
}
|
||||
)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"name": "Nothin",
|
||||
"age": 28,
|
||||
"phone": "123456789",
|
||||
"address": map[string]interface{}{
|
||||
"street": "test",
|
||||
"number": 1,
|
||||
},
|
||||
}
|
||||
|
||||
var p Person
|
||||
err := MapToStruct(m, &p)
|
||||
assert.IsNil(err)
|
||||
assert.Equal(m["name"], p.Name)
|
||||
assert.Equal(m["age"], p.Age)
|
||||
assert.Equal(m["phone"], p.Phone)
|
||||
assert.Equal("test", p.Addr.Street)
|
||||
assert.Equal(1, p.Addr.Number)
|
||||
}
|
||||
|
||||
@@ -121,6 +121,9 @@ func convertSlice(src reflect.Value, dst reflect.Value) error {
|
||||
|
||||
func convertMap(src reflect.Value, dst reflect.Value) error {
|
||||
if src.Kind() != reflect.Map || dst.Kind() != reflect.Struct {
|
||||
// if src.Kind() == reflect.Map {
|
||||
// return convertMap(src, dst)
|
||||
// } else
|
||||
if src.Kind() == reflect.Interface {
|
||||
return convertMap(src.Elem(), dst)
|
||||
} else {
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
|
||||
type (
|
||||
Person struct {
|
||||
Name string `json:"name"`
|
||||
Age int `json:"age"`
|
||||
Phone string `json:"phone"`
|
||||
Addr Address `json:"address"`
|
||||
Name string `json:"name"`
|
||||
Age int `json:"age"`
|
||||
Phone string `json:"phone"`
|
||||
Address Address `json:"address"`
|
||||
}
|
||||
|
||||
Address struct {
|
||||
@@ -41,8 +41,8 @@ func TestStructType(t *testing.T) {
|
||||
assert.Equal(src["name"], p.Name)
|
||||
assert.Equal(src["age"], p.Age)
|
||||
assert.Equal(src["phone"], p.Phone)
|
||||
assert.Equal("test", p.Addr.Street)
|
||||
assert.Equal(1, p.Addr.Number)
|
||||
assert.Equal("test", p.Address.Street)
|
||||
assert.Equal(1, p.Address.Number)
|
||||
}
|
||||
|
||||
func TestBaseType(t *testing.T) {
|
||||
|
||||
+28
-28
@@ -47,19 +47,19 @@ import (
|
||||
// Concat(streams ...StreamI[T]) StreamI[T]
|
||||
// }
|
||||
|
||||
type stream[T any] struct {
|
||||
type Stream[T any] struct {
|
||||
source []T
|
||||
}
|
||||
|
||||
// Of creates a stream whose elements are the specified values.
|
||||
// Play: https://go.dev/play/p/jI6_iZZuVFE
|
||||
func Of[T any](elems ...T) stream[T] {
|
||||
func Of[T any](elems ...T) Stream[T] {
|
||||
return FromSlice(elems)
|
||||
}
|
||||
|
||||
// Generate stream where each element is generated by the provided generater function
|
||||
// Play: https://go.dev/play/p/rkOWL1yA3j9
|
||||
func Generate[T any](generator func() func() (item T, ok bool)) stream[T] {
|
||||
func Generate[T any](generator func() func() (item T, ok bool)) Stream[T] {
|
||||
source := make([]T, 0)
|
||||
|
||||
var zeroValue T
|
||||
@@ -76,13 +76,13 @@ func Generate[T any](generator func() func() (item T, ok bool)) stream[T] {
|
||||
|
||||
// FromSlice creates stream from slice.
|
||||
// Play: https://go.dev/play/p/wywTO0XZtI4
|
||||
func FromSlice[T any](source []T) stream[T] {
|
||||
return stream[T]{source: source}
|
||||
func FromSlice[T any](source []T) Stream[T] {
|
||||
return Stream[T]{source: source}
|
||||
}
|
||||
|
||||
// FromChannel creates stream from channel.
|
||||
// Play: https://go.dev/play/p/9TZYugGMhXZ
|
||||
func FromChannel[T any](source <-chan T) stream[T] {
|
||||
func FromChannel[T any](source <-chan T) Stream[T] {
|
||||
s := make([]T, 0)
|
||||
|
||||
for v := range source {
|
||||
@@ -94,7 +94,7 @@ func FromChannel[T any](source <-chan T) stream[T] {
|
||||
|
||||
// FromRange creates a number stream from start to end. both start and end are included. [start, end]
|
||||
// Play: https://go.dev/play/p/9Ex1-zcg-B-
|
||||
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T] {
|
||||
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 {
|
||||
@@ -113,7 +113,7 @@ func FromRange[T constraints.Integer | constraints.Float](start, end, step T) st
|
||||
|
||||
// Concat creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream.
|
||||
// Play: https://go.dev/play/p/HM4OlYk_OUC
|
||||
func Concat[T any](a, b stream[T]) stream[T] {
|
||||
func Concat[T any](a, b Stream[T]) Stream[T] {
|
||||
source := make([]T, 0)
|
||||
|
||||
source = append(source, a.source...)
|
||||
@@ -124,7 +124,7 @@ func Concat[T any](a, b stream[T]) stream[T] {
|
||||
|
||||
// Distinct returns a stream that removes the duplicated items.
|
||||
// Play: https://go.dev/play/p/eGkOSrm64cB
|
||||
func (s stream[T]) Distinct() stream[T] {
|
||||
func (s Stream[T]) Distinct() Stream[T] {
|
||||
source := make([]T, 0)
|
||||
|
||||
distinct := map[string]bool{}
|
||||
@@ -153,7 +153,7 @@ func hashKey(data any) string {
|
||||
|
||||
// Filter returns a stream consisting of the elements of this stream that match the given predicate.
|
||||
// Play: https://go.dev/play/p/MFlSANo-buc
|
||||
func (s stream[T]) Filter(predicate func(item T) bool) stream[T] {
|
||||
func (s Stream[T]) Filter(predicate func(item T) bool) Stream[T] {
|
||||
source := make([]T, 0)
|
||||
|
||||
for _, v := range s.source {
|
||||
@@ -167,7 +167,7 @@ func (s stream[T]) Filter(predicate func(item T) bool) stream[T] {
|
||||
|
||||
// Map returns a stream consisting of the elements of this stream that apply the given function to elements of stream.
|
||||
// Play: https://go.dev/play/p/OtNQUImdYko
|
||||
func (s stream[T]) Map(mapper func(item T) T) stream[T] {
|
||||
func (s Stream[T]) Map(mapper func(item T) T) Stream[T] {
|
||||
source := make([]T, s.Count())
|
||||
|
||||
for i, v := range s.source {
|
||||
@@ -179,7 +179,7 @@ func (s stream[T]) Map(mapper func(item T) T) stream[T] {
|
||||
|
||||
// Peek returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
|
||||
// Play: https://go.dev/play/p/u1VNzHs6cb2
|
||||
func (s stream[T]) Peek(consumer func(item T)) stream[T] {
|
||||
func (s Stream[T]) Peek(consumer func(item T)) Stream[T] {
|
||||
for _, v := range s.source {
|
||||
consumer(v)
|
||||
}
|
||||
@@ -190,7 +190,7 @@ func (s stream[T]) Peek(consumer func(item T)) stream[T] {
|
||||
// Skip returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream.
|
||||
// If this stream contains fewer than n elements then an empty stream will be returned.
|
||||
// Play: https://go.dev/play/p/fNdHbqjahum
|
||||
func (s stream[T]) Skip(n int) stream[T] {
|
||||
func (s Stream[T]) Skip(n int) Stream[T] {
|
||||
if n <= 0 {
|
||||
return s
|
||||
}
|
||||
@@ -211,7 +211,7 @@ func (s stream[T]) Skip(n int) stream[T] {
|
||||
|
||||
// Limit returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.
|
||||
// Play: https://go.dev/play/p/qsO4aniDcGf
|
||||
func (s stream[T]) Limit(maxSize int) stream[T] {
|
||||
func (s Stream[T]) Limit(maxSize int) Stream[T] {
|
||||
if s.source == nil {
|
||||
return s
|
||||
}
|
||||
@@ -231,7 +231,7 @@ func (s stream[T]) Limit(maxSize int) stream[T] {
|
||||
|
||||
// AllMatch returns whether all elements of this stream match the provided predicate.
|
||||
// Play: https://go.dev/play/p/V5TBpVRs-Cx
|
||||
func (s stream[T]) AllMatch(predicate func(item T) bool) bool {
|
||||
func (s Stream[T]) AllMatch(predicate func(item T) bool) bool {
|
||||
for _, v := range s.source {
|
||||
if !predicate(v) {
|
||||
return false
|
||||
@@ -243,7 +243,7 @@ func (s stream[T]) AllMatch(predicate func(item T) bool) bool {
|
||||
|
||||
// AnyMatch returns whether any elements of this stream match the provided predicate.
|
||||
// Play: https://go.dev/play/p/PTCnWn4OxSn
|
||||
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool {
|
||||
func (s Stream[T]) AnyMatch(predicate func(item T) bool) bool {
|
||||
for _, v := range s.source {
|
||||
if predicate(v) {
|
||||
return true
|
||||
@@ -255,13 +255,13 @@ func (s stream[T]) AnyMatch(predicate func(item T) bool) bool {
|
||||
|
||||
// NoneMatch returns whether no elements of this stream match the provided predicate.
|
||||
// Play: https://go.dev/play/p/iWS64pL1oo3
|
||||
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool {
|
||||
func (s Stream[T]) NoneMatch(predicate func(item T) bool) bool {
|
||||
return !s.AnyMatch(predicate)
|
||||
}
|
||||
|
||||
// ForEach performs an action for each element of this stream.
|
||||
// Play: https://go.dev/play/p/Dsm0fPqcidk
|
||||
func (s stream[T]) ForEach(action func(item T)) {
|
||||
func (s Stream[T]) ForEach(action func(item T)) {
|
||||
for _, v := range s.source {
|
||||
action(v)
|
||||
}
|
||||
@@ -269,7 +269,7 @@ func (s stream[T]) ForEach(action func(item T)) {
|
||||
|
||||
// Reduce performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.
|
||||
// Play: https://go.dev/play/p/6uzZjq_DJLU
|
||||
func (s stream[T]) Reduce(initial T, accumulator func(a, b T) T) T {
|
||||
func (s Stream[T]) Reduce(initial T, accumulator func(a, b T) T) T {
|
||||
for _, v := range s.source {
|
||||
initial = accumulator(initial, v)
|
||||
}
|
||||
@@ -279,13 +279,13 @@ func (s stream[T]) Reduce(initial T, accumulator func(a, b T) T) T {
|
||||
|
||||
// Count returns the count of elements in the stream.
|
||||
// Play: https://go.dev/play/p/r3koY6y_Xo-
|
||||
func (s stream[T]) Count() int {
|
||||
func (s Stream[T]) Count() int {
|
||||
return len(s.source)
|
||||
}
|
||||
|
||||
// FindFirst returns the first element of this stream and true, or zero value and false if the stream is empty.
|
||||
// Play: https://go.dev/play/p/9xEf0-6C1e3
|
||||
func (s stream[T]) FindFirst() (T, bool) {
|
||||
func (s Stream[T]) FindFirst() (T, bool) {
|
||||
var result T
|
||||
|
||||
if s.source == nil || len(s.source) == 0 {
|
||||
@@ -297,7 +297,7 @@ func (s stream[T]) FindFirst() (T, bool) {
|
||||
|
||||
// FindLast returns the last element of this stream and true, or zero value and false if the stream is empty.
|
||||
// Play: https://go.dev/play/p/WZD2rDAW-2h
|
||||
func (s stream[T]) FindLast() (T, bool) {
|
||||
func (s Stream[T]) FindLast() (T, bool) {
|
||||
var result T
|
||||
|
||||
if s.source == nil || len(s.source) == 0 {
|
||||
@@ -309,7 +309,7 @@ func (s stream[T]) FindLast() (T, bool) {
|
||||
|
||||
// Reverse returns a stream whose elements are reverse order of given stream.
|
||||
// Play: https://go.dev/play/p/A8_zkJnLHm4
|
||||
func (s stream[T]) Reverse() stream[T] {
|
||||
func (s Stream[T]) Reverse() Stream[T] {
|
||||
l := len(s.source)
|
||||
source := make([]T, l)
|
||||
|
||||
@@ -321,7 +321,7 @@ func (s stream[T]) Reverse() stream[T] {
|
||||
|
||||
// Range returns a stream whose elements are in the range from start(included) to end(excluded) original stream.
|
||||
// Play: https://go.dev/play/p/indZY5V2f4j
|
||||
func (s stream[T]) Range(start, end int) stream[T] {
|
||||
func (s Stream[T]) Range(start, end int) Stream[T] {
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
@@ -347,7 +347,7 @@ func (s stream[T]) Range(start, end int) stream[T] {
|
||||
|
||||
// Sorted returns a stream consisting of the elements of this stream, sorted according to the provided less function.
|
||||
// Play: https://go.dev/play/p/XXtng5uonFj
|
||||
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T] {
|
||||
func (s Stream[T]) Sorted(less func(a, b T) bool) Stream[T] {
|
||||
source := []T{}
|
||||
source = append(source, s.source...)
|
||||
|
||||
@@ -359,7 +359,7 @@ func (s stream[T]) Sorted(less func(a, b T) bool) stream[T] {
|
||||
// Max returns the maximum element of this stream according to the provided less function.
|
||||
// less: a > b
|
||||
// Play: https://go.dev/play/p/fm-1KOPtGzn
|
||||
func (s stream[T]) Max(less func(a, b T) bool) (T, bool) {
|
||||
func (s Stream[T]) Max(less func(a, b T) bool) (T, bool) {
|
||||
var max T
|
||||
|
||||
if len(s.source) == 0 {
|
||||
@@ -377,7 +377,7 @@ func (s stream[T]) Max(less func(a, b T) bool) (T, bool) {
|
||||
// Min returns the minimum element of this stream according to the provided less function.
|
||||
// less: a < b
|
||||
// Play: https://go.dev/play/p/vZfIDgGNRe_0
|
||||
func (s stream[T]) Min(less func(a, b T) bool) (T, bool) {
|
||||
func (s Stream[T]) Min(less func(a, b T) bool) (T, bool) {
|
||||
var min T
|
||||
|
||||
if len(s.source) == 0 {
|
||||
@@ -395,6 +395,6 @@ func (s stream[T]) Min(less func(a, b T) bool) (T, bool) {
|
||||
|
||||
// ToSlice return the elements in the stream.
|
||||
// Play: https://go.dev/play/p/jI6_iZZuVFE
|
||||
func (s stream[T]) ToSlice() []T {
|
||||
func (s Stream[T]) ToSlice() []T {
|
||||
return s.source
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user