Documentation
¶
Overview ¶
Package sort provides primitives for sorting slices and user-defined collections.
Example ¶
package main import ( "fmt" "sort" ) type Person struct { Name string Age int } // ByAge implements sort.Interface for []Person based on // the Age field. type ByAge []Person func main() { people := []Person{ {"Bob", 31}, {"John", 42}, {"Michael", 17}, {"Jenny", 26}, } fmt.Println(people) // There are two ways to sort a slice. First, one can define // a set of methods for the slice type, as with ByAge, and // call sort.Sort. In this first example we use that technique. sort.Sort(ByAge(people)) fmt.Println(people) // The other way is to use sort.Slice with a custom Less // function, which can be provided as a closure. In this // case no methods are needed. (And if they exist, they // are ignored.) Here we re-sort in reverse order: compare // the closure with ByAge.Less. sort.Slice(people, func(i, j int) bool { return people[i].Age > people[j].Age }) fmt.Println(people) }
Output: [Bob: 31 John: 42 Michael: 17 Jenny: 26] [Michael: 17 Jenny: 26 Bob: 31 John: 42] [John: 42 Bob: 31 Jenny: 26 Michael: 17]
Example (SortKeys) ¶
ExampleSortKeys demonstrates a technique for sorting a struct type using programmable sort criteria.
package main import ( "fmt" ) // A couple of type definitions to make the units clear. // A Planet defines the properties of a solar system object. type Planet struct { name string mass earthMass 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 // planetSorter joins a By function and a slice of Planets to be sorted. // ExampleSortKeys demonstrates a technique for sorting a struct type using programmable sort criteria. func main() { // 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(p2, p1) } // 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}]
Example (SortMultiKeys) ¶
ExampleMultiKeys demonstrates a technique for sorting a struct type using different sets of multiple fields in the comparison. We chain together "Less" functions, each of which compares a single field.
package main import ( "fmt" ) // A Change is a record of source code changes, recording user, language, and delta size. type Change struct { user string language string lines int } // multiSorter implements the Sort interface, sorting the changes within. // ExampleMultiKeys demonstrates a technique for sorting a struct type using different // sets of multiple fields in the comparison. We chain together "Less" functions, each of // which compares a single field. func main() { // Closures that order the Change structure. user := func(c1, c2 *Change) bool { return c1.user < c2.user } language := func(c1, c2 *Change) bool { return c1.language < c2.language } increasingLines := func(c1, c2 *Change) bool { return c1.lines < c2.lines } decreasingLines := func(c1, c2 *Change) bool { return c1.lines > c2.lines // Note: > orders downwards. } // Simple use: Sort by user. OrderedBy(user).Sort(changes) fmt.Println("By user:", changes) // More examples. OrderedBy(user, increasingLines).Sort(changes) fmt.Println("By user,<lines:", changes) OrderedBy(user, decreasingLines).Sort(changes) fmt.Println("By user,>lines:", changes) OrderedBy(language, increasingLines).Sort(changes) fmt.Println("By language,<lines:", changes) OrderedBy(language, increasingLines, user).Sort(changes) fmt.Println("By language,<lines,user:", changes) }
Output: By user: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}] By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}] By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}] By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {r Go 100} {gri Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}] By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]
Example (SortWrapper) ¶
package main import ( "fmt" "sort" ) type Grams int type Organ struct { Name string Weight Grams } type Organs []*Organ // ByName implements sort.Interface by providing Less and using the Len and // Swap methods of the embedded Organs value. type ByName struct{ Organs } // ByWeight implements sort.Interface by providing Less and using the Len and // Swap methods of the embedded Organs value. type ByWeight struct{ Organs } func main() { s := []*Organ{ {"brain", 1340}, {"heart", 290}, {"liver", 1494}, {"pancreas", 131}, {"prostate", 62}, {"spleen", 162}, } sort.Sort(ByWeight{s}) fmt.Println("Organs by weight:") printOrgans(s) sort.Sort(ByName{s}) fmt.Println("Organs by name:") printOrgans(s) }
Output: Organs by weight: prostate (62g) pancreas (131g) spleen (162g) heart (290g) brain (1340g) liver (1494g) Organs by name: brain (1340g) heart (290g) liver (1494g) pancreas (131g) prostate (62g) spleen (162g)
Index ¶
- func Float64s(a []float64)
- func Float64sAreSorted(a []float64) bool
- func Ints(a []int)
- func IntsAreSorted(a []int) bool
- func IsSorted(data Interface) bool
- func Search(n int, f func(int) bool) int
- func SearchFloat64s(a []float64, x float64) int
- func SearchInts(a []int, x int) int
- func SearchStrings(a []string, x string) int
- func Slice(slice interface{}, less func(i, j int) bool)
- func SliceIsSorted(slice interface{}, less func(i, j int) bool) bool
- func SliceStable(slice interface{}, less func(i, j int) bool)
- func Sort(data Interface)
- func Stable(data Interface)
- func Strings(a []string)
- func StringsAreSorted(a []string) bool
- type Float64Slice
- type IntSlice
- type Interface
- type StringSlice
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Float64s ¶
func Float64s(a []float64)
Float64s sorts a slice of float64s in increasing order (not-a-number values are treated as less than other values).
Example ¶
package main import ( "fmt" "math" "sort" ) func main() { s := []float64{5.2, -1.3, 0.7, -3.8, 2.6} // unsorted sort.Float64s(s) fmt.Println(s) s = []float64{math.Inf(1), math.NaN(), math.Inf(-1), 0.0} // unsorted sort.Float64s(s) fmt.Println(s) }
Output: [-3.8 -1.3 0.7 2.6 5.2] [NaN -Inf 0 +Inf]
func Float64sAreSorted ¶
Float64sAreSorted tests whether a slice of float64s is sorted in increasing order (not-a-number values are treated as less than other values).
Example ¶
package main import ( "fmt" "sort" ) func main() { s := []float64{0.7, 1.3, 2.6, 3.8, 5.2} // sorted ascending fmt.Println(sort.Float64sAreSorted(s)) s = []float64{5.2, 3.8, 2.6, 1.3, 0.7} // sorted descending fmt.Println(sort.Float64sAreSorted(s)) s = []float64{5.2, 1.3, 0.7, 3.8, 2.6} // unsorted fmt.Println(sort.Float64sAreSorted(s)) }
Output: true false false
func Ints ¶
func Ints(a []int)
Ints sorts a slice of ints in increasing order.
Example ¶
package main import ( "fmt" "sort" ) func main() { s := []int{5, 2, 6, 3, 1, 4} // unsorted sort.Ints(s) fmt.Println(s) }
Output: [1 2 3 4 5 6]
func IntsAreSorted ¶
IntsAreSorted tests whether a slice of ints is sorted in increasing order.
Example ¶
package main import ( "fmt" "sort" ) func main() { s := []int{1, 2, 3, 4, 5, 6} // sorted ascending fmt.Println(sort.IntsAreSorted(s)) s = []int{6, 5, 4, 3, 2, 1} // sorted descending fmt.Println(sort.IntsAreSorted(s)) s = []int{3, 2, 4, 1, 5} // unsorted fmt.Println(sort.IntsAreSorted(s)) }
Output: true false false
func Search ¶
Search uses binary search to find and return the smallest index i in [0, n) at which f(i) is true, assuming that on the range [0, n), f(i) == true implies f(i+1) == true. That is, Search requires that f is false for some (possibly empty) prefix of the input range [0, n) and then true for the (possibly empty) remainder; Search returns the first true index. If there is no such index, Search returns n. (Note that the "not found" return value is not -1 as in, for instance, strings.Index.) Search calls f(i) only for i in the range [0, n).
A common use of Search is to find the index i for a value x in a sorted, indexable data structure such as an array or slice. In this case, the argument f, typically a closure, captures the value to be searched for, and how the data structure is indexed and ordered.
For instance, given a slice data sorted in ascending order, the call Search(len(data), func(i int) bool { return data[i] >= 23 }) returns the smallest index i such that data[i] >= 23. If the caller wants to find whether 23 is in the slice, it must test data[i] == 23 separately.
Searching data sorted in descending order would use the <= operator instead of the >= operator.
To complete the example above, the following code tries to find the value x in an integer slice data sorted in ascending order:
x := 23 i := sort.Search(len(data), func(i int) bool { return data[i] >= x }) if i < len(data) && data[i] == x { // x is present at data[i] } else { // x is not present in data, // but i is the index where it would be inserted. }
As a more whimsical example, this program guesses your number:
func GuessingGame() { var s string fmt.Printf("Pick an integer from 0 to 100.\n") answer := sort.Search(100, func(i int) bool { fmt.Printf("Is your number <= %d? ", i) fmt.Scanf("%s", &s) return s != "" && s[0] == 'y' }) fmt.Printf("Your number is %d.\n", answer) }
Example ¶
This example demonstrates searching a list sorted in ascending order.
package main import ( "fmt" "sort" ) func main() { a := []int{1, 3, 6, 10, 15, 21, 28, 36, 45, 55} x := 6 i := sort.Search(len(a), func(i int) bool { return a[i] >= x }) if i < len(a) && a[i] == x { fmt.Printf("found %d at index %d in %v\n", x, i, a) } else { fmt.Printf("%d not found in %v\n", x, a) } }
Output: found 6 at index 2 in [1 3 6 10 15 21 28 36 45 55]
Example (DescendingOrder) ¶
This example demonstrates searching a list sorted in descending order. The approach is the same as searching a list in ascending order, but with the condition inverted.
package main import ( "fmt" "sort" ) func main() { a := []int{55, 45, 36, 28, 21, 15, 10, 6, 3, 1} x := 6 i := sort.Search(len(a), func(i int) bool { return a[i] <= x }) if i < len(a) && a[i] == x { fmt.Printf("found %d at index %d in %v\n", x, i, a) } else { fmt.Printf("%d not found in %v\n", x, a) } }
Output: found 6 at index 7 in [55 45 36 28 21 15 10 6 3 1]
func SearchFloat64s ¶
SearchFloat64s searches for x in a sorted slice of float64s and returns the index as specified by Search. The return value is the index to insert x if x is not present (it could be len(a)). The slice must be sorted in ascending order.
func SearchInts ¶
SearchInts searches for x in a sorted slice of ints and returns the index as specified by Search. The return value is the index to insert x if x is not present (it could be len(a)). The slice must be sorted in ascending order.
func SearchStrings ¶
SearchStrings searches for x in a sorted slice of strings and returns the index as specified by Search. The return value is the index to insert x if x is not present (it could be len(a)). The slice must be sorted in ascending order.
func Slice ¶ added in v1.8.0
Slice sorts the provided slice given the provided less function.
The sort is not guaranteed to be stable. For a stable sort, use SliceStable.
The function panics if the provided interface is not a slice.
Example ¶
package main import ( "fmt" "sort" ) func main() { people := []struct { Name string Age int }{ {"Gopher", 7}, {"Alice", 55}, {"Vera", 24}, {"Bob", 75}, } sort.Slice(people, func(i, j int) bool { return people[i].Name < people[j].Name }) fmt.Println("By name:", people) sort.Slice(people, func(i, j int) bool { return people[i].Age < people[j].Age }) fmt.Println("By age:", people) }
Output: By name: [{Alice 55} {Bob 75} {Gopher 7} {Vera 24}] By age: [{Gopher 7} {Vera 24} {Alice 55} {Bob 75}]
func SliceIsSorted ¶ added in v1.8.0
SliceIsSorted tests whether a slice is sorted.
The function panics if the provided interface is not a slice.
func SliceStable ¶ added in v1.8.0
SliceStable sorts the provided slice given the provided less function while keeping the original order of equal elements.
The function panics if the provided interface is not a slice.
Example ¶
package main import ( "fmt" "sort" ) func main() { people := []struct { Name string Age int }{ {"Alice", 25}, {"Elizabeth", 75}, {"Alice", 75}, {"Bob", 75}, {"Alice", 75}, {"Bob", 25}, {"Colin", 25}, {"Elizabeth", 25}, } // Sort by name, preserving original order sort.SliceStable(people, func(i, j int) bool { return people[i].Name < people[j].Name }) fmt.Println("By name:", people) // Sort by age preserving name order sort.SliceStable(people, func(i, j int) bool { return people[i].Age < people[j].Age }) fmt.Println("By age,name:", people) }
Output: By name: [{Alice 25} {Alice 75} {Alice 75} {Bob 75} {Bob 25} {Colin 25} {Elizabeth 75} {Elizabeth 25}] By age,name: [{Alice 25} {Bob 25} {Colin 25} {Elizabeth 25} {Alice 75} {Alice 75} {Bob 75} {Elizabeth 75}]
func Sort ¶
func Sort(data Interface)
Sort sorts data. It makes one call to data.Len to determine n, and O(n*log(n)) calls to data.Less and data.Swap. The sort is not guaranteed to be stable.
func Stable ¶ added in v1.2.0
func Stable(data Interface)
Stable sorts data while keeping the original order of equal elements.
It makes one call to data.Len to determine n, O(n*log(n)) calls to data.Less and O(n*log(n)*log(n)) calls to data.Swap.
func Strings ¶
func Strings(a []string)
Strings sorts a slice of strings in increasing order.
Example ¶
package main import ( "fmt" "sort" ) func main() { s := []string{"Go", "Bravo", "Gopher", "Alpha", "Grin", "Delta"} sort.Strings(s) fmt.Println(s) }
Output: [Alpha Bravo Delta Go Gopher Grin]
func StringsAreSorted ¶
StringsAreSorted tests whether a slice of strings is sorted in increasing order.
Types ¶
type Float64Slice ¶
type Float64Slice []float64
Float64Slice attaches the methods of Interface to []float64, sorting in increasing order (not-a-number values are treated as less than other values).
func (Float64Slice) Len ¶
func (p Float64Slice) Len() int
func (Float64Slice) Less ¶
func (p Float64Slice) Less(i, j int) bool
func (Float64Slice) Search ¶
func (p Float64Slice) Search(x float64) int
Search returns the result of applying SearchFloat64s to the receiver and x.
func (Float64Slice) Swap ¶
func (p Float64Slice) Swap(i, j int)
type IntSlice ¶
type IntSlice []int
IntSlice attaches the methods of Interface to []int, sorting in increasing order.
type Interface ¶
A type, typically a collection, that satisfies sort.Interface can be sorted by the routines in this package. The methods require that the elements of the collection be enumerated by an integer index.
type StringSlice ¶
type StringSlice []string
StringSlice attaches the methods of Interface to []string, sorting in increasing order.
func (StringSlice) Len ¶
func (p StringSlice) Len() int
func (StringSlice) Less ¶
func (p StringSlice) Less(i, j int) bool
func (StringSlice) Search ¶
func (p StringSlice) Search(x string) int
Search returns the result of applying SearchStrings to the receiver and x.
func (StringSlice) Swap ¶
func (p StringSlice) Swap(i, j int)