Documentation ¶
Overview ¶
Package sorthelper provides convenience for sorting slices and user-defined collections.
Example ¶
package main import ( "fmt" "sort" "github.com/weiwenchen2022/sorthelper" ) type Person struct { Name string Age int } func (p Person) String() string { return fmt.Sprintf("%s: %d", p.Name, p.Age) } // ByAge implements sort.Interface for []Person based on // the Age field, by providing Less and using the Len and // Swap methods of the embedded slice value. type ByAge struct{ sorthelper.Slice[Person] } func (a ByAge) Less(i, j int) bool { return a.Slice[i].Age < a.Slice[j].Age } 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 sorting a struct type using Sorter with programmable sort criteria.
package main import ( "fmt" "github.com/weiwenchen2022/sorthelper" ) // A couple of type definitions to make the units clear. type earthMass float64 type au float64 // A Planet defines the properties of a solar system object. type Planet struct { name string mass earthMass distance au } 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 sorting a struct type using Sorter with 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. sorthelper.NewSorter(planets).OrderedBy(name) fmt.Println("By name:", planets) sorthelper.NewSorter(planets).OrderedBy(mass) fmt.Println("By mass:", planets) sorthelper.NewSorter(planets).OrderedBy(distance) fmt.Println("By distance:", planets) sorthelper.NewSorter(planets).OrderedBy(decreasingDistance) 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 sorting a struct type using different sets of multiple fields in the comparison. We chain together "Less" functions with MultiSorter, each of which compares a single field.
package main import ( "fmt" "github.com/weiwenchen2022/sorthelper" ) // A Change is a record of source code changes, recording user, language, and delta size. type Change struct { user string language string lines int } var changes = []Change{ {"gri", "Go", 100}, {"ken", "C", 150}, {"glenda", "Go", 200}, {"rsc", "Go", 200}, {"r", "Go", 100}, {"ken", "Go", 200}, {"dmr", "C", 100}, {"r", "C", 150}, {"gri", "Smalltalk", 80}, } // ExampleMultiKeys demonstrates sorting a struct type using different sets of multiple fields in the comparison. // We chain together "Less" functions with MultiSorter, 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. sorthelper.NewMultiSorter(changes).OrderedBy(user) fmt.Println("By user:", changes) // More examples. sorthelper.NewMultiSorter(changes).OrderedBy(user, increasingLines) fmt.Println("By user,<lines:", changes) sorthelper.NewMultiSorter(changes).OrderedBy(user, decreasingLines) fmt.Println("By user,>lines:", changes) sorthelper.NewMultiSorter(changes).OrderedBy(language, increasingLines) fmt.Println("By language,<lines:", changes) sorthelper.NewMultiSorter(changes).OrderedBy(language, increasingLines, user) 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} {gri Go 100} {r Go 100} {glenda Go 200} {ken 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" "github.com/weiwenchen2022/sorthelper" ) type Grams int func (g Grams) String() string { return fmt.Sprintf("%dg", int(g)) } type Organ struct { Name string Weight Grams } type Organs = sorthelper.Slice[*Organ] // ByName implements sort.Interface by providing Less and using the Len and // Swap methods of the embedded Organs value. type ByName struct{ Organs } func (s ByName) Less(i, j int) bool { return s.Organs[i].Name < s.Organs[j].Name } // ByWeight implements sort.Interface by providing Less and using the Len and // Swap methods of the embedded Organs value. type ByWeight struct{ Organs } func (s ByWeight) Less(i, j int) bool { return s.Organs[i].Weight < s.Organs[j].Weight } 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) } func printOrgans(s []*Organ) { for _, o := range s { fmt.Printf("%-8s (%v)\n", o.Name, o.Weight) } }
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[E ~float64](x []E)
- func Float64sAreSorted[E ~float64](x []E) bool
- func Ints[E constraints.Integer](x []E)
- func IntsAreSorted[E constraints.Integer](x []E) bool
- func Search[E constraints.Ordered](a []E, x E) int
- func SearchFloat64s[E ~float64](a []E, x E) int
- func SearchInts[E constraints.Integer](a []E, x E) int
- func SearchStrings[E ~string](a []E, x E) int
- func SliceIsSorted[E constraints.Ordered](x []E) bool
- func SliceSort[E constraints.Ordered](x []E)
- func SliceStable[E constraints.Ordered](x []E)
- func Strings[E ~string](x []E)
- func StringsAreSorted[E ~string](x []E) bool
- type Float64Slice
- type IntSlice
- type MultiSorter
- type Slice
- type Sorter
- type StringSlice
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Float64s ¶
func Float64s[E ~float64](x []E)
Float64s sorts a slice of floats in increasing order. Not-a-number (NaN) values are ordered before other values.
Example ¶
package main import ( "fmt" "math" "github.com/weiwenchen2022/sorthelper" ) func main() { type myfloat64 float64 s := []myfloat64{5.2, -1.3, 0.7, -3.8, 2.6} // unsorted sorthelper.Float64s(s) fmt.Println(s) s = []myfloat64{myfloat64(math.Inf(1)), myfloat64(math.NaN()), myfloat64(math.Inf(-1)), 0.0} // unsorted sorthelper.Float64s(s) fmt.Println(s) }
Output: [-3.8 -1.3 0.7 2.6 5.2] [NaN -Inf 0 +Inf]
func Float64sAreSorted ¶
Float64sAreSorted reports whether the slice s is sorted in increasing order, with not-a-number (NaN) values before any other values.
Example ¶
package main import ( "fmt" "github.com/weiwenchen2022/sorthelper" ) func main() { type myfloat64 float64 s := []myfloat64{0.7, 1.3, 2.6, 3.8, 5.2} // sorted ascending fmt.Println(sorthelper.Float64sAreSorted(s)) s = []myfloat64{5.2, 3.8, 2.6, 1.3, 0.7} // sorted descending fmt.Println(sorthelper.Float64sAreSorted(s)) s = []myfloat64{5.2, 1.3, 0.7, 3.8, 2.6} // unsorted fmt.Println(sorthelper.Float64sAreSorted(s)) }
Output: true false false
func Ints ¶
func Ints[E constraints.Integer](x []E)
Ints sorts a slice of ints in increasing order.
Example ¶
package main import ( "fmt" "github.com/weiwenchen2022/sorthelper" ) func main() { type myint int s := []myint{5, 2, 6, 3, 1, 4} // unsorted sorthelper.Ints(s) fmt.Println(s) }
Output: [1 2 3 4 5 6]
func IntsAreSorted ¶
func IntsAreSorted[E constraints.Integer](x []E) bool
IntsAreSorted reports whether the slice x is sorted in increasing order.
Example ¶
package main import ( "fmt" "github.com/weiwenchen2022/sorthelper" ) func main() { type myint int s := []myint{1, 2, 3, 4, 5, 6} // sorted ascending fmt.Println(sorthelper.IntsAreSorted(s)) s = []myint{6, 5, 4, 3, 2, 1} // sorted descending fmt.Println(sorthelper.IntsAreSorted(s)) s = []myint{3, 2, 4, 1, 5} // unsorted fmt.Println(sorthelper.IntsAreSorted(s)) }
Output: true false false
func Search ¶
func Search[E constraints.Ordered](a []E, x E) int
Search searches for x in a sorted slice of a and returns the index. 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.
Example ¶
This example demonstrates searching a list sorted in ascending order.
package main import ( "fmt" "github.com/weiwenchen2022/sorthelper" ) func main() { a := []int{1, 3, 6, 10, 15, 21, 28, 36, 45, 55} x := 6 i := sorthelper.Search(a, 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]
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.
Example ¶
This example demonstrates searching for float64 in a list sorted in ascending order.
package main import ( "fmt" "github.com/weiwenchen2022/sorthelper" ) func main() { type myfloat64 float64 a := []myfloat64{1.0, 2.0, 3.3, 4.6, 6.1, 7.2, 8.0} x := myfloat64(2.0) i := sorthelper.SearchFloat64s(a, x) fmt.Printf("found %g at index %d in %v\n", x, i, a) x = myfloat64(0.5) i = sorthelper.SearchFloat64s(a, x) fmt.Printf("%g not found, can be inserted at index %d in %v\n", x, i, a) }
Output: found 2 at index 1 in [1 2 3.3 4.6 6.1 7.2 8] 0.5 not found, can be inserted at index 0 in [1 2 3.3 4.6 6.1 7.2 8]
func SearchInts ¶
func SearchInts[E constraints.Integer](a []E, x E) int
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.
Example ¶
This example demonstrates searching for int in a list sorted in ascending order.
package main import ( "fmt" "github.com/weiwenchen2022/sorthelper" ) func main() { type myint int a := []myint{1, 2, 3, 4, 6, 7, 8} x := myint(2) i := sorthelper.SearchInts(a, x) fmt.Printf("found %d at index %d in %v\n", x, i, a) x = myint(5) i = sorthelper.SearchInts(a, x) fmt.Printf("%d not found, can be inserted at index %d in %v\n", x, i, a) }
Output: found 2 at index 1 in [1 2 3 4 6 7 8] 5 not found, can be inserted at index 4 in [1 2 3 4 6 7 8]
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 SliceIsSorted ¶
func SliceIsSorted[E constraints.Ordered](x []E) bool
SliceIsSorted reports whether the slice s is sorted in increasing order according to the operator <.
func SliceSort ¶
func SliceSort[E constraints.Ordered](x []E)
SliceSort sorts the slice x as determined by the operator <, in increasing order.
The sort is not guaranteed to be stable: equal elements may be reversed from their original order. For a stable sort, use StableSort.
func SliceStable ¶
func SliceStable[E constraints.Ordered](x []E)
SliceStable sorts the slice x using the operator <, in ascending order, keeping equal elements in their original order.
func Strings ¶
func Strings[E ~string](x []E)
Strings sorts a slice of strings in increasing order.
Example ¶
package main import ( "fmt" "github.com/weiwenchen2022/sorthelper" ) func main() { type mystring string s := []mystring{"Go", "Bravo", "Gopher", "Alpha", "Grin", "Delta"} sorthelper.Strings(s) fmt.Println(s) }
Output: [Alpha Bravo Delta Go Gopher Grin]
func StringsAreSorted ¶
StringsAreSorted reports whether the slice x is sorted in increasing order.
Types ¶
type Float64Slice ¶
Float64Slice implements sort.Interface by providing Less and using the Len and Swap methods of the embedded slice value, sorting in increasing order, with not-a-number (NaN) values ordered before other values.
func (Float64Slice[E]) IsSorted ¶
func (x Float64Slice[E]) IsSorted() bool
IsSorted is a convenience method: x.IsSorted() calls sort.IsSorted(x).
func (Float64Slice[E]) Less ¶
func (x Float64Slice[E]) Less(i, j int) bool
Less reports whether x[i] should be ordered before x[j], as required by the sort Interface. Note that floating-point comparison by itself is not a transitive relation: it does not report a consistent ordering for not-a-number (NaN) values. This implementation of Less places NaN values before any others, by using:
x[i] < x[j] || (math.IsNaN(x[i]) && !math.IsNaN(x[j]))
func (Float64Slice[E]) Reverse ¶
func (x Float64Slice[E]) Reverse()
Reverse is a convenience method: x.Reverse() calls sort.Sort(sort.Reverse(x)).
func (Float64Slice[E]) Search ¶
func (p Float64Slice[E]) Search(x E) int
Search returns the result of applying SearchFloat64s to the receiver and x.
func (Float64Slice[E]) Sort ¶
func (x Float64Slice[E]) Sort()
Sort is a convenience method: x.Sort() calls sort.Sort(x).
func (Float64Slice[E]) Stable ¶
func (x Float64Slice[E]) Stable()
Stable is a convenience method: x.Stable() calls sort.Stable(x).
type IntSlice ¶
type IntSlice[E constraints.Integer] struct{ Slice[E] }
IntSlice implements sort.Interface by providing Less and using the Len and Swap methods of the embedded slice value, sorting in increasing order.
func (IntSlice[E]) IsSorted ¶
IsSorted is a convenience method: x.IsSorted() calls sort.IsSorted(x).
func (IntSlice[E]) Reverse ¶
func (x IntSlice[E]) Reverse()
Reverse is a convenience method: x.Reverse() calls sorrt.Sort(sort.Reverse(x)).
type MultiSorter ¶
type MultiSorter[E any] struct { // contains filtered or unexported fields }
MultiSorter implements the Sort interface, sorting the slice within.
func NewMultiSorter ¶
func NewMultiSorter[E any](s []E) *MultiSorter[E]
NewMultiSorter returns a MulitSorter that sorts the argument slice. Call its OrderedBy method to sort the slice within using the less functions, in order.
func (*MultiSorter[E]) Len ¶
func (ms *MultiSorter[E]) Len() int
func (*MultiSorter[E]) Less ¶
func (ms *MultiSorter[E]) Less(i, j int) bool
Less is part of sort.Interface. It is implemented by looping along the less functions until it finds a comparison that discriminates between the two items (one is less than the other). Note that it can call the less functions twice per call.
func (*MultiSorter[E]) OrderedBy ¶
func (ms *MultiSorter[E]) OrderedBy(less ...func(e1, e2 *E) bool)
OrderedBy sorts the slice within according to the less functions, in order. The sort is not guaranteed to be stable. For a stable sort, use StableBy.
func (*MultiSorter[E]) StableBy ¶
func (ms *MultiSorter[E]) StableBy(less ...func(e1, e2 *E) bool)
StableBy sorts the slice within in ascending order as determined by the less functions, in order, while keeping the original order of equal elements.
func (*MultiSorter[E]) Swap ¶
func (ms *MultiSorter[E]) Swap(i, j int)
type Slice ¶
type Slice[E any] []E
Slice help implements sort.Interface by providing Len and Swap methods for embedding value.
type Sorter ¶
type Sorter[E any] struct { // contains filtered or unexported fields }
Sorter joins a by function and a slice s to be sorted.
func NewSorter ¶
NewSorter returns a Sorter that sorts the slice s. Call its OrderedBy method to sort the slice within using the by functions.
func (*Sorter[E]) Less ¶
Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (*Sorter[E]) OrderedBy ¶
OrderedBy sorts the slice within according to the by function. The sort is not guaranteed to be stable. For a stable sort, use StableBy.
type StringSlice ¶
StringSlice implements sort.Interface by providing Less and using the Len and Swap methods of the embedded slice value, sorting in increasing order.
func (StringSlice[E]) IsSorted ¶
func (x StringSlice[E]) IsSorted() bool
IsSorted is a convenience method: x.IsSorted() calls sort.IsSorted(x).
func (StringSlice[E]) Less ¶
func (x StringSlice[E]) Less(i, j int) bool
func (StringSlice[E]) Reverse ¶
func (x StringSlice[E]) Reverse()
Reverse is a convenience method: x.Reverse() calls sort.Sort(sort.Reverse(x)).
func (StringSlice[E]) Search ¶
func (p StringSlice[E]) Search(x E) int
Search returns the result of applying SearchStrings to the receiver and x.
func (StringSlice[E]) Sort ¶
func (x StringSlice[E]) Sort()
Sort is a convenience method: x.Sort() calls sort.Sort(x).
func (StringSlice[E]) Stable ¶
func (x StringSlice[E]) Stable()
Stable is a convenience method: x.Stable() calls sort.Stable(x).