|
6 | 6 | // It is similar to the unix command uniq.
|
7 | 7 | package uniq
|
8 | 8 |
|
9 |
| -import ( |
10 |
| - "fmt" |
11 |
| - "reflect" |
12 |
| -) |
13 |
| - |
14 |
| -type badTypeError struct { |
15 |
| - typ reflect.Type |
16 |
| -} |
17 |
| - |
18 |
| -func (e badTypeError) Error() string { |
19 |
| - return fmt.Sprintf("uniq.ModifySlice's first argument must have type *[]T, got %v", e.typ) |
20 |
| -} |
21 |
| - |
22 |
| -// ModifySlice removes adjacent duplicate elements from the slice pointed to by sliceptr. |
23 |
| -// It adjusts the length of the slice appropriately and zeros the tail. |
24 |
| -// eq reports whether (*sliceptr)[i] and (*sliceptr)[j] are equal. |
25 |
| -// ModifySlice does O(len(*sliceptr)) operations. |
26 |
| -func ModifySlice(sliceptr any, eq func(i, j int) bool) { |
27 |
| - rvp := reflect.ValueOf(sliceptr) |
28 |
| - if rvp.Type().Kind() != reflect.Ptr { |
29 |
| - panic(badTypeError{rvp.Type()}) |
30 |
| - } |
31 |
| - rv := rvp.Elem() |
32 |
| - if rv.Type().Kind() != reflect.Slice { |
33 |
| - panic(badTypeError{rvp.Type()}) |
34 |
| - } |
35 |
| - |
36 |
| - length := rv.Len() |
| 9 | +// ModifySlice removes adjacent duplicate elements from the given slice. It |
| 10 | +// adjusts the length of the slice appropriately and zeros the tail. |
| 11 | +// |
| 12 | +// ModifySlice does O(len(*slice)) operations. |
| 13 | +func ModifySlice[E comparable](slice *[]E) { |
| 14 | + // Remove duplicates |
37 | 15 | dst := 0
|
38 |
| - for i := 1; i < length; i++ { |
39 |
| - if eq(dst, i) { |
| 16 | + for i := 1; i < len(*slice); i++ { |
| 17 | + if (*slice)[i] == (*slice)[dst] { |
40 | 18 | continue
|
41 | 19 | }
|
42 | 20 | dst++
|
43 |
| - // slice[dst] = slice[i] |
44 |
| - rv.Index(dst).Set(rv.Index(i)) |
| 21 | + (*slice)[dst] = (*slice)[i] |
45 | 22 | }
|
46 | 23 |
|
| 24 | + // Zero out the elements we removed at the end of the slice |
47 | 25 | end := dst + 1
|
48 |
| - var zero reflect.Value |
49 |
| - if end < length { |
50 |
| - zero = reflect.Zero(rv.Type().Elem()) |
51 |
| - } |
52 |
| - |
53 |
| - // for i := range slice[end:] { |
54 |
| - // size[i] = 0/nil/{} |
55 |
| - // } |
56 |
| - for i := end; i < length; i++ { |
57 |
| - // slice[i] = 0/nil/{} |
58 |
| - rv.Index(i).Set(zero) |
| 26 | + var zero E |
| 27 | + for i := end; i < len(*slice); i++ { |
| 28 | + (*slice)[i] = zero |
59 | 29 | }
|
60 | 30 |
|
61 |
| - // slice = slice[:end] |
62 |
| - if end < length { |
63 |
| - rv.SetLen(end) |
| 31 | + // Truncate the slice |
| 32 | + if end < len(*slice) { |
| 33 | + *slice = (*slice)[:end] |
64 | 34 | }
|
65 | 35 | }
|
0 commit comments