mirror of
https://github.com/IBM/fp-go.git
synced 2025-08-08 22:27:07 +02:00
fix: add reduce and filter
Signed-off-by: Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
30
array/any.go
Normal file
30
array/any.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package array
|
||||
|
||||
import (
|
||||
G "github.com/IBM/fp-go/array/generic"
|
||||
)
|
||||
|
||||
// AnyWithIndex tests if any of the elements in the array matches the predicate
|
||||
func AnyWithIndex[A any](pred func(int, A) bool) func([]A) bool {
|
||||
return G.AnyWithIndex[[]A](pred)
|
||||
}
|
||||
|
||||
// Any tests if any of the elements in the array matches the predicate
|
||||
func Any[A any](pred func(A) bool) func([]A) bool {
|
||||
return G.Any[[]A](pred)
|
||||
}
|
30
array/any_test.go
Normal file
30
array/any_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package array
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
F "github.com/IBM/fp-go/function"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAny(t *testing.T) {
|
||||
anyBool := Any(F.Identity[bool])
|
||||
|
||||
assert.True(t, anyBool(From(false, true, false)))
|
||||
assert.False(t, anyBool(From(false, false, false)))
|
||||
}
|
@@ -60,18 +60,6 @@ func MapRef[A, B any](f func(a *A) B) func([]A) []B {
|
||||
return F.Bind2nd(MonadMapRef[A, B], f)
|
||||
}
|
||||
|
||||
func filter[A any](fa []A, pred func(A) bool) []A {
|
||||
var result []A
|
||||
count := len(fa)
|
||||
for i := 0; i < count; i++ {
|
||||
a := fa[i]
|
||||
if pred(a) {
|
||||
result = append(result, a)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func filterRef[A any](fa []A, pred func(a *A) bool) []A {
|
||||
var result []A
|
||||
count := len(fa)
|
||||
@@ -96,23 +84,38 @@ func filterMapRef[A, B any](fa []A, pred func(a *A) bool, f func(a *A) B) []B {
|
||||
return result
|
||||
}
|
||||
|
||||
// Filter returns a new array with all elements from the original array that match a predicate
|
||||
func Filter[A any](pred func(A) bool) func([]A) []A {
|
||||
return F.Bind2nd(filter[A], pred)
|
||||
return G.Filter[[]A](pred)
|
||||
}
|
||||
|
||||
// FilterWithIndex returns a new array with all elements from the original array that match a predicate
|
||||
func FilterWithIndex[A any](pred func(int, A) bool) func([]A) []A {
|
||||
return G.FilterWithIndex[[]A](pred)
|
||||
}
|
||||
|
||||
func FilterRef[A any](pred func(*A) bool) func([]A) []A {
|
||||
return F.Bind2nd(filterRef[A], pred)
|
||||
}
|
||||
|
||||
func MonadFilterMap[A, B any](fa []A, f func(a A) O.Option[B]) []B {
|
||||
func MonadFilterMap[A, B any](fa []A, f func(A) O.Option[B]) []B {
|
||||
return G.MonadFilterMap[[]A, []B](fa, f)
|
||||
}
|
||||
|
||||
// FilterChain maps an array with an iterating function that returns an [O.Option] and it keeps only the Some values discarding the Nones.
|
||||
func FilterMap[A, B any](f func(a A) O.Option[B]) func([]A) []B {
|
||||
func MonadFilterMapWithIndex[A, B any](fa []A, f func(int, A) O.Option[B]) []B {
|
||||
return G.MonadFilterMapWithIndex[[]A, []B](fa, f)
|
||||
}
|
||||
|
||||
// FilterMap maps an array with an iterating function that returns an [O.Option] and it keeps only the Some values discarding the Nones.
|
||||
func FilterMap[A, B any](f func(A) O.Option[B]) func([]A) []B {
|
||||
return G.FilterMap[[]A, []B](f)
|
||||
}
|
||||
|
||||
// FilterMapWithIndex maps an array with an iterating function that returns an [O.Option] and it keeps only the Some values discarding the Nones.
|
||||
func FilterMapWithIndex[A, B any](f func(int, A) O.Option[B]) func([]A) []B {
|
||||
return G.FilterMapWithIndex[[]A, []B](f)
|
||||
}
|
||||
|
||||
// FilterChain maps an array with an iterating function that returns an [O.Option] of an array. It keeps only the Some values discarding the Nones and then flattens the result.
|
||||
func FilterChain[A, B any](f func(A) O.Option[[]B]) func([]A) []B {
|
||||
return G.FilterChain[[]A](f)
|
||||
@@ -134,9 +137,19 @@ func reduceRef[A, B any](fa []A, f func(B, *A) B, initial B) B {
|
||||
}
|
||||
|
||||
func Reduce[A, B any](f func(B, A) B, initial B) func([]A) B {
|
||||
return func(as []A) B {
|
||||
return array.Reduce(as, f, initial)
|
||||
}
|
||||
return G.Reduce[[]A](f, initial)
|
||||
}
|
||||
|
||||
func ReduceWithIndex[A, B any](f func(int, B, A) B, initial B) func([]A) B {
|
||||
return G.ReduceWithIndex[[]A](f, initial)
|
||||
}
|
||||
|
||||
func ReduceRight[A, B any](f func(A, B) B, initial B) func([]A) B {
|
||||
return G.ReduceRight[[]A](f, initial)
|
||||
}
|
||||
|
||||
func ReduceRightWithIndex[A, B any](f func(int, A, B) B, initial B) func([]A) B {
|
||||
return G.ReduceRightWithIndex[[]A](f, initial)
|
||||
}
|
||||
|
||||
func ReduceRef[A, B any](f func(B, *A) B, initial B) func([]A) B {
|
||||
|
@@ -59,6 +59,17 @@ func TestMap(t *testing.T) {
|
||||
assert.Equal(t, dst, []string{"A", "B", "C"})
|
||||
}
|
||||
|
||||
func TestReduceRight(t *testing.T) {
|
||||
values := From("a", "b", "c")
|
||||
f := func(a, acc string) string {
|
||||
return fmt.Sprintf("%s%s", acc, a)
|
||||
}
|
||||
b := ""
|
||||
|
||||
assert.Equal(t, "cba", ReduceRight(f, b)(values))
|
||||
assert.Equal(t, "", ReduceRight(f, b)(Empty[string]()))
|
||||
}
|
||||
|
||||
func TestReduce(t *testing.T) {
|
||||
|
||||
values := MakeBy(101, F.Identity[int])
|
||||
|
77
array/example_any_test.go
Normal file
77
array/example_any_test.go
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package array
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
F "github.com/IBM/fp-go/function"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
|
||||
func Example_any() {
|
||||
|
||||
pred := func(val int) bool {
|
||||
return val&2 == 0
|
||||
}
|
||||
|
||||
data1 := From(1, 2, 3)
|
||||
|
||||
fmt.Println(Any(pred)(data1))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
|
||||
func Example_any_filter() {
|
||||
|
||||
pred := func(val int) bool {
|
||||
return val&2 == 0
|
||||
}
|
||||
|
||||
data1 := From(1, 2, 3)
|
||||
|
||||
// Any tests if any of the entries in the array matches the condition
|
||||
Any := F.Flow2(
|
||||
Filter(pred),
|
||||
IsNonEmpty[int],
|
||||
)
|
||||
|
||||
fmt.Println(Any(data1))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
|
||||
func Example_any_find() {
|
||||
|
||||
pred := func(val int) bool {
|
||||
return val&2 == 0
|
||||
}
|
||||
|
||||
data1 := From(1, 2, 3)
|
||||
|
||||
// Any tests if any of the entries in the array matches the condition
|
||||
Any := F.Flow2(
|
||||
FindFirst(pred),
|
||||
O.IsSome[int],
|
||||
)
|
||||
|
||||
fmt.Println(Any(data1))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
55
array/example_find_test.go
Normal file
55
array/example_find_test.go
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package array
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
F "github.com/IBM/fp-go/function"
|
||||
)
|
||||
|
||||
func Example_find() {
|
||||
|
||||
pred := func(val int) bool {
|
||||
return val&2 == 0
|
||||
}
|
||||
|
||||
data1 := From(1, 2, 3)
|
||||
|
||||
fmt.Println(FindFirst(pred)(data1))
|
||||
|
||||
// Output:
|
||||
// Some[int](1)
|
||||
}
|
||||
|
||||
func Example_find_filter() {
|
||||
|
||||
pred := func(val int) bool {
|
||||
return val&2 == 0
|
||||
}
|
||||
|
||||
data1 := From(1, 2, 3)
|
||||
|
||||
Find := F.Flow2(
|
||||
Filter(pred),
|
||||
Head[int],
|
||||
)
|
||||
|
||||
fmt.Println(Find(data1))
|
||||
|
||||
// Output:
|
||||
// Some[int](1)
|
||||
}
|
61
array/find.go
Normal file
61
array/find.go
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package array
|
||||
|
||||
import (
|
||||
G "github.com/IBM/fp-go/array/generic"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
|
||||
// FindFirst finds the first element which satisfies a predicate (or a refinement) function
|
||||
func FindFirst[A any](pred func(A) bool) func([]A) O.Option[A] {
|
||||
return G.FindFirst[[]A](pred)
|
||||
}
|
||||
|
||||
// FindFirstWithIndex finds the first element which satisfies a predicate (or a refinement) function
|
||||
func FindFirstWithIndex[A any](pred func(int, A) bool) func([]A) O.Option[A] {
|
||||
return G.FindFirstWithIndex[[]A](pred)
|
||||
}
|
||||
|
||||
// FindFirstMap finds the first element returned by an [O.Option] based selector function
|
||||
func FindFirstMap[A, B any](sel func(A) O.Option[B]) func([]A) O.Option[B] {
|
||||
return G.FindFirstMap[[]A](sel)
|
||||
}
|
||||
|
||||
// FindFirstMapWithIndex finds the first element returned by an [O.Option] based selector function
|
||||
func FindFirstMapWithIndex[A, B any](sel func(int, A) O.Option[B]) func([]A) O.Option[B] {
|
||||
return G.FindFirstMapWithIndex[[]A](sel)
|
||||
}
|
||||
|
||||
// FindLast finds the Last element which satisfies a predicate (or a refinement) function
|
||||
func FindLast[A any](pred func(A) bool) func([]A) O.Option[A] {
|
||||
return G.FindLast[[]A](pred)
|
||||
}
|
||||
|
||||
// FindLastWithIndex finds the Last element which satisfies a predicate (or a refinement) function
|
||||
func FindLastWithIndex[A any](pred func(int, A) bool) func([]A) O.Option[A] {
|
||||
return G.FindLastWithIndex[[]A](pred)
|
||||
}
|
||||
|
||||
// FindLastMap finds the Last element returned by an [O.Option] based selector function
|
||||
func FindLastMap[A, B any](sel func(A) O.Option[B]) func([]A) O.Option[B] {
|
||||
return G.FindLastMap[[]A](sel)
|
||||
}
|
||||
|
||||
// FindLastMapWithIndex finds the Last element returned by an [O.Option] based selector function
|
||||
func FindLastMapWithIndex[A, B any](sel func(int, A) O.Option[B]) func([]A) O.Option[B] {
|
||||
return G.FindLastMapWithIndex[[]A](sel)
|
||||
}
|
34
array/generic/any.go
Normal file
34
array/generic/any.go
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package generic
|
||||
|
||||
import (
|
||||
F "github.com/IBM/fp-go/function"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
|
||||
// AnyWithIndex tests if any of the elements in the array matches the predicate
|
||||
func AnyWithIndex[AS ~[]A, PRED ~func(int, A) bool, A any](pred PRED) func(AS) bool {
|
||||
return F.Flow2(
|
||||
FindFirstWithIndex[AS](pred),
|
||||
O.IsSome[A],
|
||||
)
|
||||
}
|
||||
|
||||
// Any tests if any of the elements in the array matches the predicate
|
||||
func Any[AS ~[]A, PRED ~func(A) bool, A any](pred PRED) func(AS) bool {
|
||||
return AnyWithIndex[AS](F.Ignore1of2[int](pred))
|
||||
}
|
@@ -29,14 +29,46 @@ func Of[GA ~[]A, A any](value A) GA {
|
||||
return GA{value}
|
||||
}
|
||||
|
||||
func Reduce[GA ~[]A, A, B any](fa GA, f func(B, A) B, initial B) B {
|
||||
func Reduce[GA ~[]A, A, B any](f func(B, A) B, initial B) func(GA) B {
|
||||
return func(as GA) B {
|
||||
return MonadReduce[GA](as, f, initial)
|
||||
}
|
||||
}
|
||||
|
||||
func ReduceWithIndex[GA ~[]A, A, B any](f func(int, B, A) B, initial B) func(GA) B {
|
||||
return func(as GA) B {
|
||||
return MonadReduceWithIndex[GA](as, f, initial)
|
||||
}
|
||||
}
|
||||
|
||||
func ReduceRight[GA ~[]A, A, B any](f func(A, B) B, initial B) func(GA) B {
|
||||
return func(as GA) B {
|
||||
return MonadReduceRight[GA](as, f, initial)
|
||||
}
|
||||
}
|
||||
|
||||
func ReduceRightWithIndex[GA ~[]A, A, B any](f func(int, A, B) B, initial B) func(GA) B {
|
||||
return func(as GA) B {
|
||||
return MonadReduceRightWithIndex[GA](as, f, initial)
|
||||
}
|
||||
}
|
||||
|
||||
func MonadReduce[GA ~[]A, A, B any](fa GA, f func(B, A) B, initial B) B {
|
||||
return array.Reduce(fa, f, initial)
|
||||
}
|
||||
|
||||
func ReduceWithIndex[GA ~[]A, A, B any](fa GA, f func(int, B, A) B, initial B) B {
|
||||
func MonadReduceWithIndex[GA ~[]A, A, B any](fa GA, f func(int, B, A) B, initial B) B {
|
||||
return array.ReduceWithIndex(fa, f, initial)
|
||||
}
|
||||
|
||||
func MonadReduceRight[GA ~[]A, A, B any](fa GA, f func(A, B) B, initial B) B {
|
||||
return array.ReduceRight(fa, f, initial)
|
||||
}
|
||||
|
||||
func MonadReduceRightWithIndex[GA ~[]A, A, B any](fa GA, f func(int, A, B) B, initial B) B {
|
||||
return array.ReduceRightWithIndex(fa, f, initial)
|
||||
}
|
||||
|
||||
// From constructs an array from a set of variadic arguments
|
||||
func From[GA ~[]A, A any](data ...A) GA {
|
||||
return data
|
||||
@@ -122,16 +154,44 @@ func Size[GA ~[]A, A any](as GA) int {
|
||||
return len(as)
|
||||
}
|
||||
|
||||
func filterMap[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(a A) O.Option[B]) GB {
|
||||
func filterMap[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(A) O.Option[B]) GB {
|
||||
return array.Reduce(fa, func(bs GB, a A) GB {
|
||||
return O.MonadFold(f(a), F.Constant(bs), F.Bind1st(Append[GB, B], bs))
|
||||
}, Empty[GB]())
|
||||
}
|
||||
|
||||
func MonadFilterMap[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(a A) O.Option[B]) GB {
|
||||
func filterMapWithIndex[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(int, A) O.Option[B]) GB {
|
||||
return array.ReduceWithIndex(fa, func(idx int, bs GB, a A) GB {
|
||||
return O.MonadFold(f(idx, a), F.Constant(bs), F.Bind1st(Append[GB, B], bs))
|
||||
}, Empty[GB]())
|
||||
}
|
||||
|
||||
func MonadFilterMap[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(A) O.Option[B]) GB {
|
||||
return filterMap[GA, GB](fa, f)
|
||||
}
|
||||
|
||||
func MonadFilterMapWithIndex[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(int, A) O.Option[B]) GB {
|
||||
return filterMapWithIndex[GA, GB](fa, f)
|
||||
}
|
||||
|
||||
func filterWithIndex[AS ~[]A, PRED ~func(int, A) bool, A any](fa AS, pred PRED) AS {
|
||||
result := make(AS, 0, len(fa))
|
||||
for i, a := range fa {
|
||||
if pred(i, a) {
|
||||
result = append(result, a)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func FilterWithIndex[AS ~[]A, PRED ~func(int, A) bool, A any](pred PRED) func(AS) AS {
|
||||
return F.Bind2nd(filterWithIndex[AS, PRED, A], pred)
|
||||
}
|
||||
|
||||
func Filter[AS ~[]A, PRED ~func(A) bool, A any](pred PRED) func(AS) AS {
|
||||
return FilterWithIndex[AS](F.Ignore1of2[int](pred))
|
||||
}
|
||||
|
||||
func FilterChain[GA ~[]A, GB ~[]B, A, B any](f func(a A) O.Option[GB]) func(GA) GB {
|
||||
return F.Flow2(
|
||||
FilterMap[GA, []GB](f),
|
||||
@@ -143,10 +203,14 @@ func Flatten[GAA ~[]GA, GA ~[]A, A any](mma GAA) GA {
|
||||
return MonadChain(mma, F.Identity[GA])
|
||||
}
|
||||
|
||||
func FilterMap[GA ~[]A, GB ~[]B, A, B any](f func(a A) O.Option[B]) func(GA) GB {
|
||||
func FilterMap[GA ~[]A, GB ~[]B, A, B any](f func(A) O.Option[B]) func(GA) GB {
|
||||
return F.Bind2nd(MonadFilterMap[GA, GB, A, B], f)
|
||||
}
|
||||
|
||||
func FilterMapWithIndex[GA ~[]A, GB ~[]B, A, B any](f func(int, A) O.Option[B]) func(GA) GB {
|
||||
return F.Bind2nd(MonadFilterMapWithIndex[GA, GB, A, B], f)
|
||||
}
|
||||
|
||||
func MonadPartition[GA ~[]A, A any](as GA, pred func(A) bool) tuple.Tuple2[GA, GA] {
|
||||
left := Empty[GA]()
|
||||
right := Empty[GA]()
|
||||
|
97
array/generic/find.go
Normal file
97
array/generic/find.go
Normal file
@@ -0,0 +1,97 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package generic
|
||||
|
||||
import (
|
||||
F "github.com/IBM/fp-go/function"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
|
||||
// FindFirstWithIndex finds the first element which satisfies a predicate (or a refinement) function
|
||||
func FindFirstWithIndex[AS ~[]A, PRED ~func(int, A) bool, A any](pred PRED) func(AS) O.Option[A] {
|
||||
none := O.None[A]()
|
||||
return func(as AS) O.Option[A] {
|
||||
for i, a := range as {
|
||||
if pred(i, a) {
|
||||
return O.Some(a)
|
||||
}
|
||||
}
|
||||
return none
|
||||
}
|
||||
}
|
||||
|
||||
// FindFirst finds the first element which satisfies a predicate (or a refinement) function
|
||||
func FindFirst[AS ~[]A, PRED ~func(A) bool, A any](pred PRED) func(AS) O.Option[A] {
|
||||
return FindFirstWithIndex[AS](F.Ignore1of2[int](pred))
|
||||
}
|
||||
|
||||
// FindFirstMapWithIndex finds the first element returned by an [O.Option] based selector function
|
||||
func FindFirstMapWithIndex[AS ~[]A, PRED ~func(int, A) O.Option[B], A, B any](pred PRED) func(AS) O.Option[B] {
|
||||
none := O.None[B]()
|
||||
return func(as AS) O.Option[B] {
|
||||
count := len(as)
|
||||
for i := 0; i < count; i++ {
|
||||
out := pred(i, as[i])
|
||||
if O.IsSome(out) {
|
||||
return out
|
||||
}
|
||||
}
|
||||
return none
|
||||
}
|
||||
}
|
||||
|
||||
// FindFirstMap finds the first element returned by an [O.Option] based selector function
|
||||
func FindFirstMap[AS ~[]A, PRED ~func(A) O.Option[B], A, B any](pred PRED) func(AS) O.Option[B] {
|
||||
return FindFirstMapWithIndex[AS](F.Ignore1of2[int](pred))
|
||||
}
|
||||
|
||||
// FindLastWithIndex finds the first element which satisfies a predicate (or a refinement) function
|
||||
func FindLastWithIndex[AS ~[]A, PRED ~func(int, A) bool, A any](pred PRED) func(AS) O.Option[A] {
|
||||
none := O.None[A]()
|
||||
return func(as AS) O.Option[A] {
|
||||
for i := len(as) - 1; i >= 0; i-- {
|
||||
a := as[i]
|
||||
if pred(i, a) {
|
||||
return O.Some(a)
|
||||
}
|
||||
}
|
||||
return none
|
||||
}
|
||||
}
|
||||
|
||||
// FindLast finds the first element which satisfies a predicate (or a refinement) function
|
||||
func FindLast[AS ~[]A, PRED ~func(A) bool, A any](pred PRED) func(AS) O.Option[A] {
|
||||
return FindLastWithIndex[AS](F.Ignore1of2[int](pred))
|
||||
}
|
||||
|
||||
// FindLastMapWithIndex finds the first element returned by an [O.Option] based selector function
|
||||
func FindLastMapWithIndex[AS ~[]A, PRED ~func(int, A) O.Option[B], A, B any](pred PRED) func(AS) O.Option[B] {
|
||||
none := O.None[B]()
|
||||
return func(as AS) O.Option[B] {
|
||||
for i := len(as) - 1; i >= 0; i-- {
|
||||
out := pred(i, as[i])
|
||||
if O.IsSome(out) {
|
||||
return out
|
||||
}
|
||||
}
|
||||
return none
|
||||
}
|
||||
}
|
||||
|
||||
// FindLastMap finds the first element returned by an [O.Option] based selector function
|
||||
func FindLastMap[AS ~[]A, PRED ~func(A) O.Option[B], A, B any](pred PRED) func(AS) O.Option[B] {
|
||||
return FindLastMapWithIndex[AS](F.Ignore1of2[int](pred))
|
||||
}
|
@@ -51,6 +51,24 @@ func ReduceWithIndex[GA ~[]A, A, B any](fa GA, f func(int, B, A) B, initial B) B
|
||||
return current
|
||||
}
|
||||
|
||||
func ReduceRight[GA ~[]A, A, B any](fa GA, f func(A, B) B, initial B) B {
|
||||
current := initial
|
||||
count := len(fa)
|
||||
for i := count - 1; i >= 0; i-- {
|
||||
current = f(fa[i], current)
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
func ReduceRightWithIndex[GA ~[]A, A, B any](fa GA, f func(int, A, B) B, initial B) B {
|
||||
current := initial
|
||||
count := len(fa)
|
||||
for i := count - 1; i >= 0; i-- {
|
||||
current = f(i, fa[i], current)
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
func Append[GA ~[]A, A any](as GA, a A) GA {
|
||||
return append(as, a)
|
||||
}
|
||||
|
@@ -63,7 +63,7 @@ func TestRetryHttp(t *testing.T) {
|
||||
check := E.Fold(
|
||||
F.Flow2(
|
||||
errors.As[*net.DNSError](),
|
||||
O.Fold(F.Constant(false), F.Constant1[*net.DNSError](true)),
|
||||
O.IsSome[*net.DNSError],
|
||||
),
|
||||
F.Constant1[*PostItem](false),
|
||||
)
|
||||
|
@@ -26,6 +26,6 @@ func Any[GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(U) bool, U any](pred FC
|
||||
return F.Flow3(
|
||||
Filter[GU](pred),
|
||||
First[GU],
|
||||
O.Fold(F.ConstFalse, F.Constant1[U](true)),
|
||||
O.IsSome[U],
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user