|
|
|
@ -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]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|