diff --git a/README.md b/README.md index 73c33223..4d4c89a4 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,8 @@ Supported helpers for slices: - [IsSorted](#issorted) - [IsSortedByKey](#issortedbykey) - [Splice](#Splice) +- [ForAll](#ForAll) +- [Exists](#Exists) Supported helpers for maps: @@ -1041,6 +1043,32 @@ result = lo.Splice([]string{"a", "b"}, 42, "1", "2") [[play](https://go.dev/play/p/G5_GhkeSUBA)] +### ForAll + +ForAll returns true if all a slice items satisfy the predicate. + +```go +result := ForAll([]int{2, 4, 6, 8}, func(x int) bool { + return x%2 == 0 +}) + // true +``` + +[[play](https://go.dev/play/p/K9Jt5gZ0HW4)] + +### Exists + +Exists returns true if at least one element satisfies the predicate. + +```go +result := Exists([]int{2, 4, 6, 8, 9}, func(x int) bool { + return x == 8 +}) + // true +``` + +[[play](https://go.dev/play/p/2lCKJ_hFUWV)] + ### Keys Creates a slice of the map keys. @@ -1062,7 +1090,7 @@ keys := lo.Keys(map[string]int{"foo": 1, "bar": 2}, map[string]int{"bar": 3}) ### UniqKeys -Creates an array of unique map keys. +Creates an array of unique map keys. ```go keys := lo.UniqKeys(map[string]int{"foo": 1, "bar": 2}, map[string]int{"baz": 3}) diff --git a/slice.go b/slice.go index d2d3fd84..744807af 100644 --- a/slice.go +++ b/slice.go @@ -693,3 +693,27 @@ func Splice[T any, Slice ~[]T](collection Slice, i int, elements ...T) Slice { return append(append(append(output, collection[:i]...), elements...), collection[i:]...) } + +// ForAll returns true if all a slice items satisfy the predicate. +// Play: https://go.dev/play/p/K9Jt5gZ0HW4 +func ForAll[T any, Slice ~[]T](collection Slice, predicate func(item T) bool) bool { + for i := range collection { + if !predicate(collection[i]) { + return false + } + } + + return true +} + +// Exists returns true if at least one element satisfies the predicate. +// Play: https://go.dev/play/p/2lCKJ_hFUWV +func Exists[T any, Slice ~[]T](collection Slice, predicate func(item T) bool) bool { + for i := range collection { + if predicate(collection[i]) { + return true + } + } + + return false +} diff --git a/slice_test.go b/slice_test.go index 9f923eea..17982075 100644 --- a/slice_test.go +++ b/slice_test.go @@ -1029,3 +1029,38 @@ func TestSplice(t *testing.T) { nonempty := Splice(allStrings, 1, "1", "2") is.IsType(nonempty, allStrings, "type preserved") } + +func TestForAll(t *testing.T) { + t.Parallel() + is := assert.New(t) + + r1 := ForAll([]int{2, 4, 6, 8}, func(x int) bool { + return x%2 == 0 + }) + is.True(r1) + + r2 := ForAll([]int{}, func(x int) bool { + return x%2 == 0 + }) + is.True(r2) + + r3 := ForAll([]int{2, 4, 6, 8, 9}, func(x int) bool { + return x%2 == 0 + }) + is.False(r3) +} + +func TestExists(t *testing.T) { + t.Parallel() + is := assert.New(t) + + r1 := Exists([]string{"one", "two", "three"}, func(x string) bool { + return x == "two" + }) + is.True(r1) + + r2 := Exists([]int{2, 4, 6, 8, 9}, func(x int) bool { + return x == 10 + }) + is.False(r2) +}