]> Cypherpunks repositories - gostls13.git/commitdiff
sort: add an example showing sorting struct by different keys
authorRob Pike <r@golang.org>
Wed, 27 Feb 2013 01:17:44 +0000 (17:17 -0800)
committerRob Pike <r@golang.org>
Wed, 27 Feb 2013 01:17:44 +0000 (17:17 -0800)
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/7376058

src/pkg/sort/example_keys_test.go [new file with mode: 0644]

diff --git a/src/pkg/sort/example_keys_test.go b/src/pkg/sort/example_keys_test.go
new file mode 100644 (file)
index 0000000..268e4da
--- /dev/null
@@ -0,0 +1,96 @@
+// Copyright 2013 The Go 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 sort_test
+
+import (
+       "fmt"
+       "sort"
+)
+
+// A couple of type definitions to make the units clear.
+type solarMass float64
+type au float64
+
+// A Planet defines the properties of a solar system object.
+type Planet struct {
+       name     string
+       mass     solarMass
+       distance au
+}
+
+// By is the type of a "less" function that defines the ordering of its Planet arguments.
+type By func(p1, p2 *Planet) bool
+
+// Sort is a method on the function type, By, that sorts the argument slice according to the function.
+func (by By) Sort(planets []Planet) {
+       ps := &planetSorter{
+               planets: planets,
+               by:      by, // The Sort method's receiver is the function (closure) that defines the sort order.
+       }
+       sort.Sort(ps)
+}
+
+// planetSorter joins a By function and a slice of Planets to be sorted.
+type planetSorter struct {
+       planets []Planet
+       by      func(p1, p2 *Planet) bool // Closure used in the Less method.
+}
+
+// Len is part of sort.Interface.
+func (s *planetSorter) Len() int {
+       return len(s.planets)
+}
+
+// Swap is part of sort.Interface.
+func (s *planetSorter) Swap(i, j int) {
+       s.planets[i], s.planets[j] = s.planets[j], s.planets[i]
+}
+
+// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
+func (s *planetSorter) Less(i, j int) bool {
+       return s.by(&s.planets[i], &s.planets[j])
+}
+
+var planets = []Planet{
+       {"Mercury", 0.055, 0.4},
+       {"Venus", 0.815, 0.7},
+       {"Earth", 1.0, 1.0},
+       {"Mars", 0.107, 1.5},
+}
+
+// ExampleSortKeys demonstrates a technique for sorting a struct type using programmable sort criteria.
+func Example_sortKeys() {
+       // Closures that order the Planet structure.
+       name := func(p1, p2 *Planet) bool {
+               return p1.name < p2.name
+       }
+       mass := func(p1, p2 *Planet) bool {
+               return p1.mass < p2.mass
+       }
+       distance := func(p1, p2 *Planet) bool {
+               return p1.distance < p2.distance
+       }
+       decreasingDistance := func(p1, p2 *Planet) bool {
+               return !distance(p1, p2)
+       }
+
+       // Sort the planets by the various criteria.
+       By(name).Sort(planets)
+       fmt.Println("By name:", planets)
+
+       By(mass).Sort(planets)
+       fmt.Println("By mass:", planets)
+
+       By(distance).Sort(planets)
+       fmt.Println("By distance:", planets)
+
+       By(decreasingDistance).Sort(planets)
+       fmt.Println("By decreasing distance:", planets)
+
+       // Output: By name: [{Earth 1 1} {Mars 0.107 1.5} {Mercury 0.055 0.4} {Venus 0.815 0.7}]
+       // By mass: [{Mercury 0.055 0.4} {Mars 0.107 1.5} {Venus 0.815 0.7} {Earth 1 1}]
+       // By distance: [{Mercury 0.055 0.4} {Venus 0.815 0.7} {Earth 1 1} {Mars 0.107 1.5}]
+       // By decreasing distance: [{Mars 0.107 1.5} {Earth 1 1} {Venus 0.815 0.7} {Mercury 0.055 0.4}]
+}