From 8b932077886df2528b0532134f048953a1c60d17 Mon Sep 17 00:00:00 2001 From: Rick Beton <1358735+rickb777@users.noreply.github.com> Date: Sun, 4 Aug 2024 16:37:41 +0100 Subject: [PATCH] Added set.Find (#18) * Added set.Exists and set.Forall methods * Replaced `Exists`/`Forall` with new `Find` method in `set` --- set/set.go | 23 +++++++++++++++++++++++ set/set_test.go | 13 +++++++++++++ 2 files changed, 36 insertions(+) diff --git a/set/set.go b/set/set.go index 98ec546..5edd720 100644 --- a/set/set.go +++ b/set/set.go @@ -67,6 +67,29 @@ func (s Of[T]) Equal(other Of[T]) bool { return true } +// Find returns the first value for which a function applied to the value +// returns true. If the function does not return true for any value +// in the set, Find returns false and the zero value of T. +// +// if several set elements would match, the first match will be chosen +// arbitrarily because the iteration order is indeterminate. +// +// Find can also be used for two special cases: +// - To test whether any value exists that matches the predicate, +// a true boolean result is all that matters. +// - To test whether any value exists that does not match the predicate, +// in this case the inverse function should be supplied and +// a false result is all that matters. +func (s Of[T]) Find(f func(T) bool) (T, bool) { + for val := range s { + if f(val) { + return val, true + } + } + var zero T + return zero, false +} + // Each calls a function on each element of the set in an indeterminate order. // It is safe to add and remove items during a call to Each, // but that can affect the sequence of values seen later during the same Each call. diff --git a/set/set_test.go b/set/set_test.go index aa34624..65d1d2b 100644 --- a/set/set_test.go +++ b/set/set_test.go @@ -24,6 +24,19 @@ func TestSet(t *testing.T) { t.Errorf("got %v, want [1 2 3 4 5 6]", got) } + v1, exists1 := s.Find(func(val int) bool { return val > 3 }) + if !exists1 { + t.Errorf("Find(val > 3) failed") + } + if v1 <= 3 { + t.Errorf("Find(val > 3) failed with %d", v1) + } + + _, exists2 := s.Find(func(val int) bool { return val > 10 }) + if exists2 { + t.Errorf("Find(val > 10) failed") + } + s2 := New[int](5, 6, 7, 8) i := Intersect(s, s2) if !reflect.DeepEqual(i, Of[int](map[int]struct{}{5: {}, 6: {}})) {