Skip to content

Commit 36b1ca2

Browse files
authored
Add Delete function (#194)
Delete removes elements at indices in idx from input slice, returns resulting slice. If an index is out of bounds, skip it.
1 parent 90bf328 commit 36b1ca2

8 files changed

Lines changed: 138 additions & 2 deletions

File tree

v2/delete.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package pie
2+
3+
import "sort"
4+
5+
// Removes elements at indices in idx from input slice, returns resulting slice.
6+
// If an index is out of bounds, skip it.
7+
func Delete[T any](ss []T, idx ...int) []T {
8+
// short path O(n) inplace
9+
if len(idx) == 1 {
10+
i := idx[0]
11+
12+
if i < 0 || i >= len(ss) {
13+
return ss
14+
}
15+
return append(ss[:i], ss[i+1:]...)
16+
}
17+
18+
// long path O(mLog(m) + n)
19+
sort.Ints(idx)
20+
21+
ss2 := make([]T, 0, len(ss))
22+
23+
prev := 0
24+
for _, i := range idx {
25+
if i < 0 || i >= len(ss) {
26+
continue
27+
}
28+
// Copy by consecutive chunks instead of one by one
29+
ss2 = append(ss2, ss[prev:i]...)
30+
prev = i + 1
31+
}
32+
ss2 = append(ss2, ss[prev:]...)
33+
34+
return ss2
35+
}

v2/delete_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package pie_test
2+
3+
import (
4+
"github.com/elliotchance/pie/v2"
5+
"github.com/stretchr/testify/assert"
6+
"testing"
7+
)
8+
9+
var deleteTests = []struct {
10+
ss []int
11+
idx []int
12+
expected []int
13+
}{
14+
// idx out of bounds
15+
{
16+
[]int{1, 2},
17+
[]int{-1},
18+
[]int{1, 2},
19+
},
20+
{
21+
[]int{1, 2},
22+
[]int{2},
23+
[]int{1, 2},
24+
},
25+
// remove from empty slice
26+
{
27+
[]int{},
28+
[]int{0},
29+
[]int{},
30+
},
31+
{
32+
[]int{1},
33+
[]int{0},
34+
[]int{},
35+
},
36+
{
37+
[]int{1, 2, 3, 4, 5},
38+
[]int{2},
39+
[]int{1, 2, 4, 5},
40+
},
41+
{
42+
[]int{1, 2, 3, 4, 5},
43+
[]int{1, 3},
44+
[]int{1, 3, 5},
45+
},
46+
// mixed indices
47+
{
48+
[]int{1, 2, 3, 4, 5},
49+
[]int{1, -1, 5, 3},
50+
[]int{1, 3, 5},
51+
},
52+
}
53+
54+
func TestDelete(t *testing.T) {
55+
for _, test := range deleteTests {
56+
57+
t.Run("", func(t *testing.T) {
58+
assert.Equal(t, test.expected, pie.Delete(test.ss, test.idx...))
59+
})
60+
}
61+
}

v2/of.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,9 @@ func (o OfSlice[T]) Top(n int) OfSlice[T] {
203203
func (o OfSlice[T]) Unshift(elements ...T) OfSlice[T] {
204204
return OfSlice[T]{Unshift(o.Result, elements...)}
205205
}
206+
207+
// Removes element at index in idx from input slice, returns resulting slice.
208+
// If an index in idx out of bounds, skip it.
209+
func (o OfSlice[T]) Delete(idx ...int) OfSlice[T] {
210+
return OfSlice[T]{Delete(o.Result, idx...)}
211+
}

v2/of_numeric.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ package pie
22

33
import (
44
"context"
5-
"golang.org/x/exp/constraints"
65
"math/rand"
6+
7+
"golang.org/x/exp/constraints"
78
)
89

910
// OfNumeric encapsulates a slice to be used in multiple chained operations.
@@ -231,3 +232,7 @@ func (o OfNumericSlice[T]) Unique() OfNumericSlice[T] {
231232
func (o OfNumericSlice[T]) Unshift(elements ...T) OfNumericSlice[T] {
232233
return OfNumericSlice[T]{Unshift(o.Result, elements...)}
233234
}
235+
236+
func (o OfNumericSlice[T]) Delete(idx ...int) OfNumericSlice[T] {
237+
return OfNumericSlice[T]{Delete(o.Result, idx...)}
238+
}

v2/of_numeric_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,12 @@ func TestOfONumeric(t *testing.T) {
2323

2424
assert.Equal(t, []float64{1.23}, names)
2525
})
26+
27+
t.Run("delete", func(t *testing.T) {
28+
names := pie.OfNumeric([]float64{1.23, 4.56}).
29+
Delete(1).
30+
Result
31+
32+
assert.Equal(t, []float64{1.23}, names)
33+
})
2634
}

v2/of_ordered.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ package pie
22

33
import (
44
"context"
5-
"golang.org/x/exp/constraints"
65
"math/rand"
6+
7+
"golang.org/x/exp/constraints"
78
)
89

910
// OfOrdered encapsulates a slice to be used in multiple chained operations.
@@ -199,3 +200,7 @@ func (o OfOrderedSlice[T]) Unique() OfOrderedSlice[T] {
199200
func (o OfOrderedSlice[T]) Unshift(elements ...T) OfOrderedSlice[T] {
200201
return OfOrderedSlice[T]{Unshift(o.Result, elements...)}
201202
}
203+
204+
func (o OfOrderedSlice[T]) Delete(idx ...int) OfOrderedSlice[T] {
205+
return OfOrderedSlice[T]{Delete(o.Result, idx...)}
206+
}

v2/of_ordered_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,12 @@ func TestOfOrdered(t *testing.T) {
2323

2424
assert.Equal(t, []string{"Bob"}, names)
2525
})
26+
27+
t.Run("delete", func(t *testing.T) {
28+
names := pie.Of([]string{"Bob", "Sally", "John", "Jane"}).
29+
Delete(2, 3).
30+
Result
31+
32+
assert.Equal(t, []string{"Bob", "Sally"}, names)
33+
})
2634
}

v2/of_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,12 @@ func TestOf(t *testing.T) {
2828

2929
assert.Equal(t, []string{"Bob", "Sally"}, names)
3030
})
31+
32+
t.Run("delete", func(t *testing.T) {
33+
names := pie.Of([]string{"Bob", "Sally", "John", "Jane"}).
34+
Delete(2, 3).
35+
Result
36+
37+
assert.Equal(t, []string{"Bob", "Sally"}, names)
38+
})
3139
}

0 commit comments

Comments
 (0)