|
|
|
|
@ -6,60 +6,30 @@ |
|
|
|
|
// It is similar to the unix command uniq.
|
|
|
|
|
package uniq |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"fmt" |
|
|
|
|
"reflect" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
type badTypeError struct { |
|
|
|
|
typ reflect.Type |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e badTypeError) Error() string { |
|
|
|
|
return fmt.Sprintf("uniq.ModifySlice's first argument must have type *[]T, got %v", e.typ) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ModifySlice removes adjacent duplicate elements from the slice pointed to by sliceptr.
|
|
|
|
|
// It adjusts the length of the slice appropriately and zeros the tail.
|
|
|
|
|
// eq reports whether (*sliceptr)[i] and (*sliceptr)[j] are equal.
|
|
|
|
|
// ModifySlice does O(len(*sliceptr)) operations.
|
|
|
|
|
func ModifySlice(sliceptr any, eq func(i, j int) bool) { |
|
|
|
|
rvp := reflect.ValueOf(sliceptr) |
|
|
|
|
if rvp.Type().Kind() != reflect.Ptr { |
|
|
|
|
panic(badTypeError{rvp.Type()}) |
|
|
|
|
} |
|
|
|
|
rv := rvp.Elem() |
|
|
|
|
if rv.Type().Kind() != reflect.Slice { |
|
|
|
|
panic(badTypeError{rvp.Type()}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
length := rv.Len() |
|
|
|
|
// ModifySlice removes adjacent duplicate elements from the given slice. It
|
|
|
|
|
// adjusts the length of the slice appropriately and zeros the tail.
|
|
|
|
|
//
|
|
|
|
|
// ModifySlice does O(len(*slice)) operations.
|
|
|
|
|
func ModifySlice[E comparable](slice *[]E) { |
|
|
|
|
// Remove duplicates
|
|
|
|
|
dst := 0 |
|
|
|
|
for i := 1; i < length; i++ { |
|
|
|
|
if eq(dst, i) { |
|
|
|
|
for i := 1; i < len(*slice); i++ { |
|
|
|
|
if (*slice)[i] == (*slice)[dst] { |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
dst++ |
|
|
|
|
// slice[dst] = slice[i]
|
|
|
|
|
rv.Index(dst).Set(rv.Index(i)) |
|
|
|
|
(*slice)[dst] = (*slice)[i] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Zero out the elements we removed at the end of the slice
|
|
|
|
|
end := dst + 1 |
|
|
|
|
var zero reflect.Value |
|
|
|
|
if end < length { |
|
|
|
|
zero = reflect.Zero(rv.Type().Elem()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// for i := range slice[end:] {
|
|
|
|
|
// size[i] = 0/nil/{}
|
|
|
|
|
// }
|
|
|
|
|
for i := end; i < length; i++ { |
|
|
|
|
// slice[i] = 0/nil/{}
|
|
|
|
|
rv.Index(i).Set(zero) |
|
|
|
|
var zero E |
|
|
|
|
for i := end; i < len(*slice); i++ { |
|
|
|
|
(*slice)[i] = zero |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// slice = slice[:end]
|
|
|
|
|
if end < length { |
|
|
|
|
rv.SetLen(end) |
|
|
|
|
// Truncate the slice
|
|
|
|
|
if end < len(*slice) { |
|
|
|
|
*slice = (*slice)[:end] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|