diff --git a/examples/sorting-by-functions/sorting-by-functions.go b/examples/sorting-by-functions/sorting-by-functions.go index 8524f668a..d54d79ecd 100644 --- a/examples/sorting-by-functions/sorting-by-functions.go +++ b/examples/sorting-by-functions/sorting-by-functions.go @@ -7,39 +7,47 @@ package main import ( + "cmp" "fmt" - "sort" + "slices" ) -// In order to sort by a custom function in Go, we need a -// corresponding type. Here we've created a `byLength` -// type that is just an alias for the builtin `[]string` -// type. -type byLength []string - -// We implement `sort.Interface` - `Len`, `Less`, and -// `Swap` - on our type so we can use the `sort` package's -// generic `Sort` function. `Len` and `Swap` -// will usually be similar across types and `Less` will -// hold the actual custom sorting logic. In our case we -// want to sort in order of increasing string length, so -// we use `len(s[i])` and `len(s[j])` here. -func (s byLength) Len() int { - return len(s) -} -func (s byLength) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} -func (s byLength) Less(i, j int) bool { - return len(s[i]) < len(s[j]) -} - -// With all of this in place, we can now implement our -// custom sort by converting the original `fruits` slice -// to `byLength`, and then use `sort.Sort` on that typed -// slice. func main() { fruits := []string{"peach", "banana", "kiwi"} - sort.Sort(byLength(fruits)) + + // We implement a comparison function for string + // lengths. `cmp.Compare` is helpful for this. + lenCmp := func(a, b string) int { + return cmp.Compare(len(a), len(b)) + } + + // Now we can call `slices.SortFunc` with this custom + // comparison function to sort `fruits` by name length. + slices.SortFunc(fruits, lenCmp) fmt.Println(fruits) + + // We can use the same technique to sort a slice of + // values that aren't built-in types. + type Person struct { + name string + age int + } + + people := []Person{ + Person{name: "Jax", age: 37}, + Person{name: "TJ", age: 25}, + Person{name: "Alex", age: 72}, + } + + // Sort `people` by age using `slices.SortFunc`. + // + // Note: if the `Person` struct is large, + // you may want the slice to contain `*Person` instead + // and adjust the sorting function accordingly. If in + // doubt, [benchmark](testing-and-benchmarking)! + slices.SortFunc(people, + func(a, b Person) int { + return cmp.Compare(a.age, b.age) + }) + fmt.Println(people) } diff --git a/examples/sorting-by-functions/sorting-by-functions.hash b/examples/sorting-by-functions/sorting-by-functions.hash index ff61f8111..8413a1003 100644 --- a/examples/sorting-by-functions/sorting-by-functions.hash +++ b/examples/sorting-by-functions/sorting-by-functions.hash @@ -1,2 +1,2 @@ -e5a6006366e05ee7785eebac8ba588e4b937a197 -h4g4vaLBtkw +9902d1c5654b64d8b381ea7888c0793ac8ab4a97 +3EaTknAZHMu diff --git a/examples/sorting-by-functions/sorting-by-functions.sh b/examples/sorting-by-functions/sorting-by-functions.sh index d2a1c4c40..eb8b9b4a3 100644 --- a/examples/sorting-by-functions/sorting-by-functions.sh +++ b/examples/sorting-by-functions/sorting-by-functions.sh @@ -1,10 +1,3 @@ -# Running our program shows a list sorted by string -# length, as desired. $ go run sorting-by-functions.go [kiwi peach banana] - -# By following this same pattern of creating a custom -# type, implementing the three `Interface` methods on that -# type, and then calling sort.Sort on a collection of that -# custom type, we can sort Go slices by arbitrary -# functions. +[{TJ 25} {Jax 37} {Alex 72}] diff --git a/public/sorting-by-functions b/public/sorting-by-functions index 77b833c04..43e5f4752 100644 --- a/public/sorting-by-functions +++ b/public/sorting-by-functions @@ -45,7 +45,7 @@ in Go.

- +
package main
@@ -57,98 +57,114 @@ in Go.

import (
+    "cmp"
     "fmt"
-    "sort"
+    "slices"
 )
-

In order to sort by a custom function in Go, we need a -corresponding type. Here we’ve created a byLength -type that is just an alias for the builtin []string -type.

- + -
type byLength []string
+
func main() {
+    fruits := []string{"peach", "banana", "kiwi"}
-

We implement sort.Interface - Len, Less, and -Swap - on our type so we can use the sort package’s -generic Sort function. Len and Swap -will usually be similar across types and Less will -hold the actual custom sorting logic. In our case we -want to sort in order of increasing string length, so -we use len(s[i]) and len(s[j]) here.

+

We implement a comparison function for string +lengths. cmp.Compare is helpful for this.

-
func (s byLength) Len() int {
-    return len(s)
-}
-func (s byLength) Swap(i, j int) {
-    s[i], s[j] = s[j], s[i]
-}
-func (s byLength) Less(i, j int) bool {
-    return len(s[i]) < len(s[j])
-}
+
    lenCmp := func(a, b string) int {
+        return cmp.Compare(len(a), len(b))
+    }
-

With all of this in place, we can now implement our -custom sort by converting the original fruits slice -to byLength, and then use sort.Sort on that typed -slice.

+

Now we can call slices.SortFunc with this custom +comparison function to sort fruits by name length.

- + -
func main() {
-    fruits := []string{"peach", "banana", "kiwi"}
-    sort.Sort(byLength(fruits))
-    fmt.Println(fruits)
-}
+
    slices.SortFunc(fruits, lenCmp)
+    fmt.Println(fruits)
- - - - + + + + + - + + +
-

Running our program shows a list sorted by string -length, as desired.

+

We can use the same technique to sort a slice of +values that aren’t built-in types.

-
$ go run sorting-by-functions.go 
-[kiwi peach banana]
+
    type Person struct {
+        name string
+        age  int
+    }
+
+ + + +
    people := []Person{
+        Person{name: "Jax", age: 37},
+        Person{name: "TJ", age: 25},
+        Person{name: "Alex", age: 72},
+    }
-

By following this same pattern of creating a custom -type, implementing the three Interface methods on that -type, and then calling sort.Sort on a collection of that -custom type, we can sort Go slices by arbitrary -functions.

+

Sort people by age using slices.SortFunc.

+ +

Note: if the Person struct is large, +you may want the slice to contain *Person instead +and adjust the sorting function accordingly. If in +doubt, benchmark!

+ - +
    slices.SortFunc(people,
+        func(a, b Person) int {
+            return cmp.Compare(a.age, b.age)
+        })
+    fmt.Println(people)
+}
+
+ + + + + + @@ -167,7 +183,7 @@ functions.

+ + + +
$ go run sorting-by-functions.go 
+[kiwi peach banana]
+[{TJ 25} {Jax 37} {Alex 72}]