1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-12-11 23:17:16 +02:00

Compare commits

..

2 Commits

Author SHA1 Message Date
Dr. Carsten Leue
3bf432af49 fix: add a uniq method to arrays
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2023-11-30 09:02:38 +01:00
Carsten Leue
b6efa35b03 fix: bug in compact array (#87)
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2023-11-29 22:13:46 +01:00
8 changed files with 98 additions and 6 deletions

32
array/generic/uniq.go Normal file
View File

@@ -0,0 +1,32 @@
package generic
import F "github.com/IBM/fp-go/function"
// StrictUniq converts an array of arbitrary items into an array or unique items
// where uniqueness is determined by the built-in uniqueness constraint
func StrictUniq[AS ~[]A, A comparable](as AS) AS {
return Uniq[AS](F.Identity[A])(as)
}
// uniquePredUnsafe returns a predicate on a map for uniqueness
func uniquePredUnsafe[PRED ~func(A) K, A any, K comparable](f PRED) func(int, A) bool {
lookup := make(map[K]bool)
return func(_ int, a A) bool {
k := f(a)
_, has := lookup[k]
if has {
return false
}
lookup[k] = true
return true
}
}
// Uniq converts an array of arbitrary items into an array or unique items
// where uniqueness is determined based on a key extractor function
func Uniq[AS ~[]A, PRED ~func(A) K, A any, K comparable](f PRED) func(as AS) AS {
return func(as AS) AS {
// we need to create a new predicate for each iteration
return filterWithIndex(as, uniquePredUnsafe(f))
}
}

17
array/uniq.go Normal file
View File

@@ -0,0 +1,17 @@
package array
import (
G "github.com/IBM/fp-go/array/generic"
)
// StrictUniq converts an array of arbitrary items into an array or unique items
// where uniqueness is determined by the built-in uniqueness constraint
func StrictUniq[A comparable](as []A) []A {
return G.StrictUniq[[]A](as)
}
// Uniq converts an array of arbitrary items into an array or unique items
// where uniqueness is determined based on a key extractor function
func Uniq[A any, K comparable](f func(A) K) func(as []A) []A {
return G.Uniq[[]A](f)
}

14
array/uniq_test.go Normal file
View File

@@ -0,0 +1,14 @@
package array
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestUniq(t *testing.T) {
data := From(1, 2, 3, 2, 4, 1)
uniq := StrictUniq(data)
assert.Equal(t, From(1, 2, 3, 4), uniq)
}

View File

@@ -61,14 +61,14 @@ func SequenceArray[E, A any](ma []Either[E, A]) Either[E, []A] {
return SequenceArrayG[[]A](ma) return SequenceArrayG[[]A](ma)
} }
// CompactArrayG discards the none values and keeps the some values // CompactArrayG discards the none values and keeps the right values
func CompactArrayG[A1 ~[]Either[E, A], A2 ~[]A, E, A any](fa A1) A2 { func CompactArrayG[A1 ~[]Either[E, A], A2 ~[]A, E, A any](fa A1) A2 {
return RA.Reduce(fa, func(out A2, value Either[E, A]) A2 { return RA.Reduce(fa, func(out A2, value Either[E, A]) A2 {
return MonadFold(value, F.Constant1[E](out), F.Bind1st(RA.Append[A2, A], out)) return MonadFold(value, F.Constant1[E](out), F.Bind1st(RA.Append[A2, A], out))
}, make(A2, len(fa))) }, make(A2, 0, len(fa)))
} }
// CompactArray discards the none values and keeps the some values // CompactArray discards the none values and keeps the right values
func CompactArray[E, A any](fa []Either[E, A]) []A { func CompactArray[E, A any](fa []Either[E, A]) []A {
return CompactArrayG[[]Either[E, A], []A](fa) return CompactArrayG[[]Either[E, A], []A](fa)
} }

18
either/array_test.go Normal file
View File

@@ -0,0 +1,18 @@
package either
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestCompactArray(t *testing.T) {
ar := []Either[string, string]{
Of[string]("ok"),
Left[string]("err"),
Of[string]("ok"),
}
res := CompactArray(ar)
assert.Equal(t, 2, len(res))
}

View File

@@ -19,13 +19,13 @@ import (
G "github.com/IBM/fp-go/iterator/stateless/generic" G "github.com/IBM/fp-go/iterator/stateless/generic"
) )
// StrictUniq converts an [Iterator] or arbitrary items into an [Iterator] or unique items // StrictUniq converts an [Iterator] of arbitrary items into an [Iterator] or unique items
// where uniqueness is determined by the built-in uniqueness constraint // where uniqueness is determined by the built-in uniqueness constraint
func StrictUniq[A comparable](as Iterator[A]) Iterator[A] { func StrictUniq[A comparable](as Iterator[A]) Iterator[A] {
return G.StrictUniq[Iterator[A]](as) return G.StrictUniq[Iterator[A]](as)
} }
// Uniq converts an [Iterator] or arbitrary items into an [Iterator] or unique items // Uniq converts an [Iterator] of arbitrary items into an [Iterator] or unique items
// where uniqueness is determined based on a key extractor function // where uniqueness is determined based on a key extractor function
func Uniq[A any, K comparable](f func(A) K) func(as Iterator[A]) Iterator[A] { func Uniq[A any, K comparable](f func(A) K) func(as Iterator[A]) Iterator[A] {
return G.Uniq[Iterator[A], K](f) return G.Uniq[Iterator[A], K](f)

View File

@@ -65,7 +65,7 @@ func SequenceArray[A any](ma []Option[A]) Option[[]A] {
func CompactArrayG[A1 ~[]Option[A], A2 ~[]A, A any](fa A1) A2 { func CompactArrayG[A1 ~[]Option[A], A2 ~[]A, A any](fa A1) A2 {
return RA.Reduce(fa, func(out A2, value Option[A]) A2 { return RA.Reduce(fa, func(out A2, value Option[A]) A2 {
return MonadFold(value, F.Constant(out), F.Bind1st(RA.Append[A2, A], out)) return MonadFold(value, F.Constant(out), F.Bind1st(RA.Append[A2, A], out))
}, make(A2, len(fa))) }, make(A2, 0, len(fa)))
} }
// CompactArray discards the none values and keeps the some values // CompactArray discards the none values and keeps the some values

View File

@@ -34,3 +34,14 @@ func TestSequenceArray(t *testing.T) {
assert.Equal(t, res, Of([]int{1, 2})) assert.Equal(t, res, Of([]int{1, 2}))
} }
func TestCompactArray(t *testing.T) {
ar := []Option[string]{
Of("ok"),
None[string](),
Of("ok"),
}
res := CompactArray(ar)
assert.Equal(t, 2, len(res))
}