Skip to content

Commit

Permalink
Merge branch 'nicklaus-dev-nick-add-without-by'
Browse files Browse the repository at this point in the history
  • Loading branch information
samber committed Jan 25, 2025
2 parents 7166d51 + 4201d6e commit 64e89e4
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 0 deletions.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ Supported intersection helpers:
- [Difference](#difference)
- [Union](#union)
- [Without](#without)
- [WithoutBy](#withoutby)
- [WithoutEmpty](#withoutempty)
- [WithoutNth](#withoutnth)

Expand Down Expand Up @@ -2198,6 +2199,39 @@ subset := lo.Without([]int{0, 2, 10}, 0, 1, 2, 3, 4, 5)
// []int{10}
```

### WithoutBy

Filters a slice by excluding elements whose extracted keys match any in the exclude list.

It returns a new slice containing only the elements whose keys are not in the exclude list.


```go
type struct User {
ID int
Name string
}

// original users
users := []User{
{ID: 1, Name: "Alice"},
{ID: 2, Name: "Bob"},
{ID: 3, Name: "Charlie"},
}

// extract function to get the user ID
getID := func(user User) int {
return user.ID
}

// exclude users with IDs 2 and 3
excludedIDs := []int{2, 3}

// filtering users
filteredUsers := lo.WithoutBy(users, getID, excludedIDs...)
// []User[{ID: 1, Name: "Alice"}]
```

### WithoutEmpty

Returns slice excluding zero values.
Expand Down
17 changes: 17 additions & 0 deletions intersect.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,23 @@ func Without[T comparable, Slice ~[]T](collection Slice, exclude ...T) Slice {
return result
}

// WithoutBy filters a slice by excluding elements whose extracted keys match any in the exclude list.
// It returns a new slice containing only the elements whose keys are not in the exclude list.
func WithoutBy[T any, K comparable](collection []T, iteratee func(item T) K, exclude ...K) []T {
excludeMap := make(map[K]struct{}, len(exclude))
for _, e := range exclude {
excludeMap[e] = struct{}{}
}

result := make([]T, 0, len(collection))
for _, item := range collection {
if _, ok := excludeMap[iteratee(item)]; !ok {
result = append(result, item)
}
}
return result
}

// WithoutEmpty returns slice excluding zero values.
//
// Deprecated: Use lo.Compact instead.
Expand Down
34 changes: 34 additions & 0 deletions intersect_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package lo

import (
"fmt"
)

func ExampleWithoutBy() {
type User struct {
ID int
Name string
}
// original users
users := []User{
{ID: 1, Name: "Alice"},
{ID: 2, Name: "Bob"},
{ID: 3, Name: "Charlie"},
}

// exclude users with IDs 2 and 3
excludedIDs := []int{2, 3}

// extract function to get the user ID
extractID := func(user User) int {
return user.ID
}

// filtering users
filteredUsers := WithoutBy(users, extractID, excludedIDs...)

// output the filtered users
fmt.Printf("%v\n", filteredUsers)
// Output:
// [{1 Alice}]
}
20 changes: 20 additions & 0 deletions intersect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,26 @@ func TestWithout(t *testing.T) {
is.IsType(nonempty, allStrings, "type preserved")
}

func TestWithoutBy(t *testing.T) {
t.Parallel()
is := assert.New(t)

type User struct {
Name string
Age int
}

result1 := WithoutBy([]User{{Name: "nick"}, {Name: "peter"}},
func(item User) string {
return item.Name
}, "nick", "lily")
result2 := WithoutBy([]User{}, func(item User) int { return item.Age }, 1, 2, 3)
result3 := WithoutBy([]User{}, func(item User) string { return item.Name })
is.Equal(result1, []User{{Name: "peter"}})
is.Equal(result2, []User{})
is.Equal(result3, []User{})
}

func TestWithoutEmpty(t *testing.T) {
t.Parallel()
is := assert.New(t)
Expand Down

0 comments on commit 64e89e4

Please sign in to comment.