"math"
"slices"
"sort"
+ "strings"
"testing"
"unsafe"
)
// Sort by customer first, product second, and last by higher price
slices.SortFunc(orders, func(a, b Order) int {
return cmp.Or(
- cmp.Compare(a.Customer, b.Customer),
- cmp.Compare(a.Product, b.Product),
+ strings.Compare(a.Customer, b.Customer),
+ strings.Compare(a.Product, b.Product),
cmp.Compare(b.Price, a.Price),
)
})
return 0
}
+func CompareString(a, b string) int {
+ return runtime_cmpstring(a, b)
+}
+
//go:linkname runtime_cmpstring runtime.cmpstring
func runtime_cmpstring(a, b string) int {
l := len(a)
//go:noescape
func Compare(a, b []byte) int
+func CompareString(a, b string) int {
+ return abigen_runtime_cmpstring(a, b)
+}
+
// The declaration below generates ABI wrappers for functions
// implemented in assembly in this package but declared in another
// package.
{"Gopher", 13},
}
n, found := slices.BinarySearchFunc(people, Person{"Bob", 0}, func(a, b Person) int {
- return cmp.Compare(a.Name, b.Name)
+ return strings.Compare(a.Name, b.Name)
})
fmt.Println("Bob:", n, found)
// Output:
func ExampleIsSortedFunc() {
names := []string{"alice", "Bob", "VERA"}
isSortedInsensitive := slices.IsSortedFunc(names, func(a, b string) int {
- return cmp.Compare(strings.ToLower(a), strings.ToLower(b))
+ return strings.Compare(strings.ToLower(a), strings.ToLower(b))
})
fmt.Println(isSortedInsensitive)
fmt.Println(slices.IsSorted(names))
func ExampleSortFunc_caseInsensitive() {
names := []string{"Bob", "alice", "VERA"}
slices.SortFunc(names, func(a, b string) int {
- return cmp.Compare(strings.ToLower(a), strings.ToLower(b))
+ return strings.Compare(strings.ToLower(a), strings.ToLower(b))
})
fmt.Println(names)
// Output:
{"Alice", 20},
}
slices.SortFunc(people, func(a, b Person) int {
- if n := cmp.Compare(a.Name, b.Name); n != 0 {
+ if n := strings.Compare(a.Name, b.Name); n != 0 {
return n
}
// If names are equal, order by age
}
// Stable sort by name, keeping age ordering of Alices intact
slices.SortStableFunc(people, func(a, b Person) int {
- return cmp.Compare(a.Name, b.Name)
+ return strings.Compare(a.Name, b.Name)
})
fmt.Println(people)
// Output:
package slices_test
import (
+ "cmp"
"fmt"
"slices"
+ "strings"
"testing"
)
}
midpoint := len(structs) / 2
needle := &myStruct{n: (structs[midpoint].n + structs[midpoint+1].n) / 2}
- lessFunc := func(a, b *myStruct) int { return a.n - b.n }
+ cmpFunc := func(a, b *myStruct) int { return a.n - b.n }
b.ResetTimer()
for i := 0; i < b.N; i++ {
- slices.BinarySearchFunc(structs, needle, lessFunc)
+ slices.BinarySearchFunc(structs, needle, cmpFunc)
+ }
+ })
+ }
+}
+
+func BenchmarkSortFuncStruct(b *testing.B) {
+ for _, size := range []int{16, 32, 64, 128, 512, 1024} {
+ b.Run(fmt.Sprintf("Size%d", size), func(b *testing.B) {
+ structs := make([]*myStruct, size)
+ for i := range structs {
+ structs[i] = &myStruct{
+ a: fmt.Sprintf("string%d", i%10),
+ n: i * 11 % size,
+ }
+ }
+ cmpFunc := func(a, b *myStruct) int {
+ if n := strings.Compare(a.a, b.a); n != 0 {
+ return n
+ }
+ return cmp.Compare(a.n, b.n)
+ }
+ // Presort the slice so all benchmark iterations are identical.
+ slices.SortFunc(structs, cmpFunc)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ // Sort the slice twice because slices.SortFunc modifies the slice in place.
+ slices.SortFunc(structs, func(a, b *myStruct) int { return cmpFunc(b, a) })
+ slices.SortFunc(structs, cmpFunc)
}
})
}
package strings
+import "internal/bytealg"
+
// Compare returns an integer comparing two strings lexicographically.
// The result will be 0 if a == b, -1 if a < b, and +1 if a > b.
//
-// Compare is included only for symmetry with package bytes.
-// It is usually clearer and always faster to use the built-in
-// string comparison operators ==, <, >, and so on.
+// Use Compare when you need to perform a three-way comparison (with
+// slices.SortFunc, for example). It is usually clearer and always faster
+// to use the built-in string comparison operators ==, <, >, and so on.
func Compare(a, b string) int {
- // NOTE(rsc): This function does NOT call the runtime cmpstring function,
- // because we do not want to provide any performance justification for
- // using strings.Compare. Basically no one should use strings.Compare.
- // As the comment above says, it is here only for symmetry with package bytes.
- // If performance is important, the compiler should be changed to recognize
- // the pattern so that all code doing three-way comparisons, not just code
- // using strings.Compare, can benefit.
- if a == b {
- return 0
- }
- if a < b {
- return -1
- }
- return +1
+ return bytealg.CompareString(a, b)
}