2020-10-01 20:56:46 +00:00
|
|
|
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
// Package uniq provides removal of adjacent duplicate elements in slices.
|
|
|
|
// It is similar to the unix command uniq.
|
|
|
|
package uniq
|
|
|
|
|
2022-08-30 21:56:51 +00:00
|
|
|
// 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
|
2020-10-01 20:56:46 +00:00
|
|
|
dst := 0
|
2022-08-30 21:56:51 +00:00
|
|
|
for i := 1; i < len(*slice); i++ {
|
|
|
|
if (*slice)[i] == (*slice)[dst] {
|
2020-10-01 20:56:46 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
dst++
|
2022-08-30 21:56:51 +00:00
|
|
|
(*slice)[dst] = (*slice)[i]
|
2020-10-01 20:56:46 +00:00
|
|
|
}
|
|
|
|
|
2022-08-30 21:56:51 +00:00
|
|
|
// Zero out the elements we removed at the end of the slice
|
2020-10-01 20:56:46 +00:00
|
|
|
end := dst + 1
|
2022-08-30 21:56:51 +00:00
|
|
|
var zero E
|
|
|
|
for i := end; i < len(*slice); i++ {
|
|
|
|
(*slice)[i] = zero
|
2020-10-01 20:56:46 +00:00
|
|
|
}
|
|
|
|
|
2022-08-30 21:56:51 +00:00
|
|
|
// Truncate the slice
|
|
|
|
if end < len(*slice) {
|
|
|
|
*slice = (*slice)[:end]
|
2020-10-01 20:56:46 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-30 22:51:18 +00:00
|
|
|
|
|
|
|
// ModifySliceFunc is the same as ModifySlice except that it allows using a
|
|
|
|
// custom comparison function.
|
|
|
|
//
|
|
|
|
// eq should report whether the two provided elements are equal.
|
|
|
|
func ModifySliceFunc[E any](slice *[]E, eq func(i, j E) bool) {
|
|
|
|
// Remove duplicates
|
|
|
|
dst := 0
|
|
|
|
for i := 1; i < len(*slice); i++ {
|
|
|
|
if eq((*slice)[dst], (*slice)[i]) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
dst++
|
|
|
|
(*slice)[dst] = (*slice)[i]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Zero out the elements we removed at the end of the slice
|
|
|
|
end := dst + 1
|
|
|
|
var zero E
|
|
|
|
for i := end; i < len(*slice); i++ {
|
|
|
|
(*slice)[i] = zero
|
|
|
|
}
|
|
|
|
|
|
|
|
// Truncate the slice
|
|
|
|
if end < len(*slice) {
|
|
|
|
*slice = (*slice)[:end]
|
|
|
|
}
|
|
|
|
}
|