diff --git a/slice/slice.go b/slice/slice.go index e89f0c7..7469061 100644 --- a/slice/slice.go +++ b/slice/slice.go @@ -7,6 +7,7 @@ package slice import ( "errors" "fmt" + "math" "reflect" "sort" "strings" @@ -332,6 +333,37 @@ func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error return v.Interface(), nil } +// Drop creates a slice with `n` elements dropped from the beginning when n > 0, or `n` elements dropped from the ending when n < 0 +func Drop(slice interface{}, n int) interface{} { + sv := sliceValue(slice) + + if n == 0 { + return slice + } + + svLen := sv.Len() + + if math.Abs(float64(n)) >= float64(svLen) { + return reflect.MakeSlice(sv.Type(), 0, 0).Interface() + } + + if n > 0 { + res := reflect.MakeSlice(sv.Type(), svLen-n, svLen-n) + for i := 0; i < res.Len(); i++ { + res.Index(i).Set(sv.Index(i + n)) + } + + return res.Interface() + } else { + res := reflect.MakeSlice(sv.Type(), svLen+n, svLen+n) + for i := 0; i < res.Len(); i++ { + res.Index(i).Set(sv.Index(i)) + } + + return res.Interface() + } +} + // InsertByIndex insert the element into slice at index. // Insert value: s = append(s[:i], append([]T{x}, s[i:]...)...) // Insert slice: a = append(a[:i], append(b, a[i:]...)...) diff --git a/slice/slice_test.go b/slice/slice_test.go index 45b4e04..e7eee33 100644 --- a/slice/slice_test.go +++ b/slice/slice_test.go @@ -326,6 +326,29 @@ func deleteByIndex(t *testing.T, origin, test interface{}, start, end int, expec } } +func TestDrop(t *testing.T) { + drop(t, []int{}, 0, []int{}) + drop(t, []int{}, 1, []int{}) + drop(t, []int{}, -1, []int{}) + + drop(t, []int{1, 2, 3, 4, 5}, 0, []int{1, 2, 3, 4, 5}) + drop(t, []int{1, 2, 3, 4, 5}, 1, []int{2, 3, 4, 5}) + drop(t, []int{1, 2, 3, 4, 5}, 5, []int{}) + drop(t, []int{1, 2, 3, 4, 5}, 6, []int{}) + + drop(t, []int{1, 2, 3, 4, 5}, -1, []int{1, 2, 3, 4}) + drop(t, []int{1, 2, 3, 4, 5}, -5, []int{}) + drop(t, []int{1, 2, 3, 4, 5}, -6, []int{}) +} + +func drop(t *testing.T, test interface{}, n int, expected interface{}) { + res := Drop(test, n) + if !reflect.DeepEqual(res, expected) { + internal.LogFailedTestInfo(t, "Drop", test, expected, res) + t.FailNow() + } +} + func TestInsertByIndex(t *testing.T) { t1 := []string{"a", "b", "c"}