Added DropByIndex helper for slice (#398)

* added DropByIndex helper

---------

Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
This commit is contained in:
Owen Gong
2024-06-30 06:38:34 +08:00
committed by GitHub
parent 93686db8b5
commit 52e17faeec
5 changed files with 95 additions and 0 deletions

View File

@@ -747,6 +747,18 @@ l := lo.DropRightWhile([]string{"a", "aa", "aaa", "aa", "aa"}, func(val string)
[[play](https://go.dev/play/p/3-n71oEC0Hz)] [[play](https://go.dev/play/p/3-n71oEC0Hz)]
### DropByIndex
Drops elements from a slice or array by the index. A negative index will drop elements from the end of the slice.
```go
l := lo.Drop([]int{0, 1, 2, 3, 4, 5}, 2, 4, -1)
// []int{2, 3}
```
[[play](https://go.dev/play/p/JswS7vXRJP2)]
### Reject ### Reject
The opposite of Filter, this method returns the elements of collection that predicate does not return truthy for. The opposite of Filter, this method returns the elements of collection that predicate does not return truthy for.

View File

@@ -1,6 +1,7 @@
package lo package lo
import ( import (
"sort"
"math/rand" "math/rand"
"github.com/samber/lo/internal/constraints" "github.com/samber/lo/internal/constraints"
@@ -417,6 +418,38 @@ func DropRightWhile[T any, Slice ~[]T](collection Slice, predicate func(item T)
return append(result, collection[:i+1]...) return append(result, collection[:i+1]...)
} }
// DropByIndex drops elements from a slice or array by the index.
// A negative index will drop elements from the end of the slice.
// Play: https://go.dev/play/p/bPIH4npZRxS
func DropByIndex[T any](collection []T, indexes ...int) []T {
initialSize := len(collection)
if initialSize == 0 {
return make([]T, 0)
}
for i := range indexes {
if indexes[i] < 0 {
indexes[i] = initialSize + indexes[i]
}
}
indexes = Uniq(indexes)
sort.Ints(indexes)
result := make([]T, 0, initialSize)
result = append(result, collection...)
for i := range indexes {
if indexes[i]-i < 0 || indexes[i]-i >= initialSize-i {
continue
}
result = append(result[:indexes[i]-i], result[indexes[i]-i+1:]...)
}
return result
}
// Reject is the opposite of Filter, this method returns the elements of collection that predicate does not return truthy for. // Reject is the opposite of Filter, this method returns the elements of collection that predicate does not return truthy for.
// Play: https://go.dev/play/p/YkLMODy1WEL // Play: https://go.dev/play/p/YkLMODy1WEL
func Reject[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) bool) Slice { func Reject[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) bool) Slice {

View File

@@ -151,6 +151,26 @@ func BenchmarkDropRightWhile(b *testing.B) {
} }
} }
func BenchmarkDropByIndex(b *testing.B) {
for _, n := range lengths {
strs := genSliceString(n)
b.Run(fmt.Sprintf("strings_%d", n), func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = DropByIndex(strs, n/4)
}
})
}
for _, n := range lengths {
ints := genSliceInt(n)
b.Run(fmt.Sprintf("ints%d", n), func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = DropByIndex(ints, n/4)
}
})
}
}
func BenchmarkReplace(b *testing.B) { func BenchmarkReplace(b *testing.B) {
lengths := []int{1_000, 10_000, 100_000} lengths := []int{1_000, 10_000, 100_000}
for _, n := range lengths { for _, n := range lengths {

View File

@@ -296,6 +296,15 @@ func ExampleDropRightWhile() {
// Output: [0 1 2] // Output: [0 1 2]
} }
func ExampleDropByIndex() {
list := []int{0, 1, 2, 3, 4, 5}
result := DropByIndex(list, 2)
fmt.Printf("%v", result)
// Output: [0 1 3 4 5]
}
func ExampleReject() { func ExampleReject() {
list := []int{0, 1, 2, 3, 4, 5} list := []int{0, 1, 2, 3, 4, 5}

View File

@@ -571,6 +571,27 @@ func TestDropRightWhile(t *testing.T) {
is.IsType(nonempty, allStrings, "type preserved") is.IsType(nonempty, allStrings, "type preserved")
} }
func TestDropByIndex(t *testing.T) {
t.Parallel()
is := assert.New(t)
is.Equal([]int{1, 2, 3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, 0))
is.Equal([]int{3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, 0, 1, 2))
is.Equal([]int{0, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, -4, -2, -3))
is.Equal([]int{0, 2, 3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, -4, -4))
is.Equal([]int{2, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, 3, 1, 0))
is.Equal([]int{0, 1, 3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, 2))
is.Equal([]int{0, 1, 2, 3}, DropByIndex([]int{0, 1, 2, 3, 4}, 4))
is.Equal([]int{0, 1, 2, 3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, 5))
is.Equal([]int{0, 1, 2, 3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, 100))
is.Equal([]int{0, 1, 2, 3}, DropByIndex([]int{0, 1, 2, 3, 4}, -1))
is.Equal([]int{}, DropByIndex([]int{}, 0, 1))
is.Equal([]int{}, DropByIndex([]int{42}, 0, 1))
is.Equal([]int{}, DropByIndex([]int{42}, 1, 0))
is.Equal([]int{}, DropByIndex([]int{}, 1))
is.Equal([]int{}, DropByIndex([]int{1}, 0))
}
func TestReject(t *testing.T) { func TestReject(t *testing.T) {
t.Parallel() t.Parallel()
is := assert.New(t) is := assert.New(t)