Skip to content

Commit

Permalink
sets: implement a RemoveFunc() for removing elements matching a condi…
Browse files Browse the repository at this point in the history
…tion (#26)
  • Loading branch information
shoenig authored Feb 12, 2023
1 parent d07967c commit f6e63c4
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Implements the following set operations
- Remove
- RemoveAll
- RemoveSet
- RemoveFunc
- Contains
- ContainsAll
- Subset
Expand Down
14 changes: 14 additions & 0 deletions hashset.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,20 @@ func (s *HashSet[T, H]) RemoveSet(o *HashSet[T, H]) bool {
return modified
}

// RemoveFunc will remove each element from s that satisfies condition f.
//
// Return true if s was modified, false otherwise.
func (s *HashSet[T, H]) RemoveFunc(f func(item T) bool) bool {
modified := false
for _, item := range s.items {
if applies := f(item); applies {
s.Remove(item)
modified = true
}
}
return modified
}

// Contains returns whether item is present in s.
func (s *HashSet[T, H]) Contains(item T) bool {
_, exists := s.items[item.Hash()]
Expand Down
41 changes: 41 additions & 0 deletions hashset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,47 @@ func TestHashSet_RemoveSet(t *testing.T) {
})
}

func TestHashSet_RemoveFunc(t *testing.T) {
t.Run("empty", func(t *testing.T) {
s := NewHashSet[*company, string](10)
modified := s.RemoveFunc(func(c *company) bool {
return c.floor > 3
})
must.Empty(t, s)
must.False(t, modified)
})

t.Run("none match", func(t *testing.T) {
s := HashSetFrom[*company, string]([]*company{c1, c2, c3})
modified := s.RemoveFunc(func(c *company) bool {
return c.floor > 3
})
must.False(t, modified)
must.Size(t, 3, s)
})

t.Run("some match", func(t *testing.T) {
s := HashSetFrom[*company, string]([]*company{c1, c2, c3, c4, c5, c6})
modified := s.RemoveFunc(func(c *company) bool {
return c.floor > 3
})
must.True(t, modified)
must.Size(t, 3, s)
must.Contains[*company](t, c1, s)
must.Contains[*company](t, c2, s)
must.Contains[*company](t, c3, s)
})

t.Run("all match", func(t *testing.T) {
s := HashSetFrom[*company, string]([]*company{c1, c2, c3, c4, c5, c6})
modified := s.RemoveFunc(func(c *company) bool {
return c.floor >= 0
})
must.True(t, modified)
must.Empty(t, s)
})
}

func TestHashSet_Contains(t *testing.T) {
t.Run("empty contains", func(t *testing.T) {
a := NewHashSet[*company, string](0)
Expand Down
14 changes: 14 additions & 0 deletions set.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,20 @@ func (s *Set[T]) RemoveSet(o *Set[T]) bool {
return modified
}

// RemoveFunc will remove each element from s that satisfies condition f.
//
// Return true if s was modified, false otherwise.
func (s *Set[T]) RemoveFunc(f func(item T) bool) bool {
modified := false
for item := range s.items {
if applies := f(item); applies {
s.Remove(item)
modified = true
}
}
return modified
}

// Contains returns whether item is present in s.
func (s *Set[T]) Contains(item T) bool {
_, exists := s.items[item]
Expand Down
38 changes: 38 additions & 0 deletions set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,44 @@ func TestSet_RemoveSet(t *testing.T) {
})
}

func TestSet_RemoveFunc(t *testing.T) {
t.Run("empty", func(t *testing.T) {
a := New[int](10)
modified := a.RemoveFunc(func(i int) bool {
return i%2 == 0
})
must.Empty(t, a)
must.False(t, modified)
})

t.Run("none match", func(t *testing.T) {
a := From[int]([]int{1, 3, 5, 7, 9})
modified := a.RemoveFunc(func(i int) bool {
return i%2 == 0
})
must.True(t, a.ContainsSlice([]int{1, 3, 5, 7, 9}))
must.False(t, modified)
})

t.Run("some match", func(t *testing.T) {
a := From[int]([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})
modified := a.RemoveFunc(func(i int) bool {
return i%2 == 0
})
must.True(t, a.ContainsSlice([]int{1, 3, 5, 7, 9}))
must.True(t, modified)
})

t.Run("all match", func(t *testing.T) {
a := From[int]([]int{1, 3, 5, 7, 9})
modified := a.RemoveFunc(func(i int) bool {
return i%2 != 0
})
must.Empty(t, a)
must.True(t, modified)
})
}

func TestSet_Copy(t *testing.T) {
t.Run("copy empty", func(t *testing.T) {
a := New[int](0)
Expand Down

0 comments on commit f6e63c4

Please sign in to comment.