Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(slice): add SplitBy function to split slices based on an iteratee #434

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Expand Up @@ -116,6 +116,7 @@ Supported helpers for slices:
- [Compact](#compact)
- [IsSorted](#issorted)
- [IsSortedByKey](#issortedbykey)
- [SplitBy](#splitby)

Supported helpers for maps:

Expand Down Expand Up @@ -924,6 +925,20 @@ slice := lo.IsSortedByKey([]string{"a", "bb", "ccc"}, func(s string) int {

[[play](https://go.dev/play/p/wiG6XyBBu49)]

### SplitBy

Split a slice in two based on a predicate.

```go
right, left := lo.SplitBy([]string{"a", "bb", "ccc"}, func(_ string, index int) int {
return index%2 == 0
})
// []string{"a", "ccc"}
// []string{"bb"}
```

[[play](https://go.dev/play/p/todo)] <!-- TODO -->

### Keys

Creates an array of the map keys.
Expand Down
15 changes: 15 additions & 0 deletions slice.go
Expand Up @@ -592,3 +592,18 @@ func IsSortedByKey[T any, K constraints.Ordered](collection []T, iteratee func(i

return true
}

// SplitBy splits an input slice into two output slices depending on the predicate function.
//
// If the function returns true, then the element is placed in the first output slice.
// If not, the element is placed in the second output slice.
func SplitBy[T any](s []T, predicate func(item T, index int) bool) (s1 []T, s2 []T) {
for i, e := range s {
if predicate(e, i) {
s1 = append(s1, e)
} else {
s2 = append(s2, e)
}
}
return
}
22 changes: 20 additions & 2 deletions slice_test.go
Expand Up @@ -388,7 +388,7 @@ func TestAssociate(t *testing.T) {

func TestSliceToMap(t *testing.T) {
t.Parallel()

type foo struct {
baz string
bar int
Expand Down Expand Up @@ -626,7 +626,7 @@ func TestSlice(t *testing.T) {
out16 := Slice(in, -10, 1)
out17 := Slice(in, -1, 3)
out18 := Slice(in, -10, 7)

is.Equal([]int{}, out1)
is.Equal([]int{0}, out2)
is.Equal([]int{0, 1, 2, 3, 4}, out3)
Expand Down Expand Up @@ -759,3 +759,21 @@ func TestIsSortedByKey(t *testing.T) {
return ret
}))
}

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

// Arrange
in := []string{"a", "b", "c", "d", "e", "f", "g"}

// Act
right, left := SplitBy(in, func(_ string, index int) bool {
return index%2 == 0
})

// Assert
is.Equal(right, []string{"a", "c", "e", "g"})
is.Equal(left, []string{"b", "d", "f"})
is.ElementsMatch(in, append(right, left...))
}