diff --git a/changes/20250108150125.feature b/changes/20250108150125.feature new file mode 100644 index 0000000000..6e0ae8c127 --- /dev/null +++ b/changes/20250108150125.feature @@ -0,0 +1 @@ +:sparkles: `[collection]` add helpers easier to use with slices diff --git a/utils/collection/search.go b/utils/collection/search.go index e47c33404b..678d8e0d62 100644 --- a/utils/collection/search.go +++ b/utils/collection/search.go @@ -59,6 +59,9 @@ func UniqueEntries[T comparable](slice []T) []T { // Any returns true if there is at least one element of the slice which is true. func Any(slice []bool) bool { + if len(slice) == 0 { + return false + } for i := range slice { if slice[i] { return true @@ -67,6 +70,21 @@ func Any(slice []bool) bool { return false } +// AnyTrue returns whether there is a value set to true +func AnyTrue(values ...bool) bool { + return Any(values) +} + +// AnyFunc returns whether there is at least one element of slice s for which f() returns true. +func AnyFunc[S ~[]E, E any](s S, f func(E) bool) bool { + all := make([]bool, 0, len(s)) + for i := range s { + all = append(all, f(s[i])) + + } + return Any(all) +} + // AnyEmpty returns whether there is one entry in the slice which is empty. // If strict, then whitespaces are considered as empty strings func AnyEmpty(strict bool, slice []string) bool { @@ -76,6 +94,9 @@ func AnyEmpty(strict bool, slice []string) bool { // All returns true if all items of the slice are true. func All(slice []bool) bool { + if len(slice) == 0 { + return false + } for i := range slice { if !slice[i] { return false @@ -84,6 +105,21 @@ func All(slice []bool) bool { return true } +// AllTrue returns whether all values are true. +func AllTrue(values ...bool) bool { + return All(values) +} + +// AllFunc returns whether f returns true for all the elements of slice s. +func AllFunc[S ~[]E, E any](s S, f func(E) bool) bool { + all := make([]bool, 0, len(s)) + for i := range s { + all = append(all, f(s[i])) + + } + return All(all) +} + // AllNotEmpty returns whether all elements of the slice are not empty. // If strict, then whitespaces are considered as empty strings func AllNotEmpty(strict bool, slice []string) bool { diff --git a/utils/collection/search_test.go b/utils/collection/search_test.go index 7cc0b6984e..115fe8fb53 100644 --- a/utils/collection/search_test.go +++ b/utils/collection/search_test.go @@ -58,19 +58,58 @@ func TestFindInSlice(t *testing.T) { } func TestAny(t *testing.T) { + assert.False(t, Any([]bool{})) assert.True(t, Any([]bool{false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false})) assert.False(t, Any([]bool{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false})) assert.True(t, Any([]bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true})) assert.True(t, Any([]bool{true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true})) } +func TestAnyTrue(t *testing.T) { + assert.False(t, AnyTrue()) + assert.True(t, AnyTrue(false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false)) + assert.False(t, AnyTrue(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false)) + assert.True(t, AnyTrue(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true)) + assert.True(t, AnyTrue(true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true)) +} + +func TestAnyFunc(t *testing.T) { + f := func(v bool) bool { + return v + } + assert.False(t, AnyFunc([]bool{}, f)) + assert.True(t, AnyFunc([]bool{false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false}, f)) + assert.False(t, AnyFunc([]bool{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, f)) + assert.True(t, AnyFunc([]bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true}, f)) + assert.True(t, AnyFunc([]bool{true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true}, f)) +} + func TestAll(t *testing.T) { + assert.False(t, All([]bool{})) assert.False(t, All([]bool{false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false})) assert.False(t, All([]bool{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false})) assert.True(t, All([]bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true})) assert.False(t, All([]bool{true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true})) } +func TestAllTrue(t *testing.T) { + assert.False(t, AllTrue(false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false)) + assert.False(t, AllTrue(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false)) + assert.True(t, AllTrue(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true)) + assert.False(t, AllTrue(true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true)) +} + +func TestAllFunc(t *testing.T) { + f := func(v bool) bool { + return v + } + assert.False(t, AllFunc([]bool{}, f)) + assert.False(t, AllFunc([]bool{false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false}, f)) + assert.False(t, AllFunc([]bool{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, f)) + assert.True(t, AllFunc([]bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true}, f)) + assert.False(t, AllFunc([]bool{true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true}, f)) +} + func TestAnyEmpty(t *testing.T) { assert.True(t, AnyEmpty(false, []string{faker.Username(), faker.Name(), faker.Sentence(), ""})) assert.False(t, AnyEmpty(false, []string{faker.Username(), " ", faker.Name(), faker.Sentence()}))