slices: return quickly for Compact of one element
Change-Id: I993c34b2cedc18da3500d3ddcbdeeb6bbc73d10f
GitHub-Last-Rev: 1620ea09e9518260e03d909734d9f6fbad5122de
GitHub-Pull-Request: golang/exp#46
Reviewed-on: https://go-review.googlesource.com/c/exp/+/448878
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/slices/slices.go b/slices/slices.go
index 0c756c4..ff8b5d8 100644
--- a/slices/slices.go
+++ b/slices/slices.go
@@ -193,7 +193,7 @@
// This is like the uniq command found on Unix.
// Compact modifies the contents of the slice s; it does not create a new slice.
func Compact[S ~[]E, E comparable](s S) S {
- if len(s) == 0 {
+ if len(s) < 2 {
return s
}
i := 1
@@ -210,7 +210,7 @@
// CompactFunc is like Compact but uses a comparison function.
func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
- if len(s) == 0 {
+ if len(s) < 2 {
return s
}
i := 1
diff --git a/slices/slices_test.go b/slices/slices_test.go
index 367dcf1..35ccad5 100644
--- a/slices/slices_test.go
+++ b/slices/slices_test.go
@@ -497,30 +497,37 @@
}
var compactTests = []struct {
+ name string
s []int
want []int
}{
{
+ "nil",
nil,
nil,
},
{
+ "one",
[]int{1},
[]int{1},
},
{
+ "sorted",
[]int{1, 2, 3},
[]int{1, 2, 3},
},
{
+ "1 item",
[]int{1, 1, 2},
[]int{1, 2},
},
{
+ "unsorted",
[]int{1, 2, 1},
[]int{1, 2, 1},
},
{
+ "many",
[]int{1, 2, 2, 3, 3, 4},
[]int{1, 2, 3, 4},
},
@@ -535,6 +542,20 @@
}
}
+func BenchmarkCompact(b *testing.B) {
+ for _, c := range compactTests {
+ b.Run(c.name, func(b *testing.B) {
+ ss := make([]int, 0, 64)
+ for k := 0; k < b.N; k++ {
+ ss = ss[:0]
+ ss = append(ss, c.s...)
+ _ = Compact(ss)
+ }
+ })
+ }
+
+}
+
func TestCompactFunc(t *testing.T) {
for _, test := range compactTests {
copy := Clone(test.s)