sorting-by-functions
This commit is contained in:
parent
f777d74cc5
commit
5594a438c1
@ -1,54 +1,45 @@
|
|||||||
// ## Sorting by Functions
|
// ## Sorting by Functions
|
||||||
|
|
||||||
// Sorting a slice by a function is a bit tricker in Go
|
// Sometimes we'll want to sort a collection by something
|
||||||
// than you may be used to in other languages. Let's look
|
// other than its natural order. For example, suppose we
|
||||||
// at some examples to see how it works.
|
// wanted to sort strings by their length instead of
|
||||||
|
// alphabetically. Here's an example of custom sorts sorts
|
||||||
|
// in Go.
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
import "sort"
|
import "sort"
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
type Person struct {
|
// In order to sort by a custom function in Go, we need a
|
||||||
Name string
|
// corresponding type. Here we've created a `ByLength`
|
||||||
Age int
|
// type that is just an alias for the builtin `[]string`
|
||||||
}
|
// type.
|
||||||
|
type ByLength []string
|
||||||
type ByName []Person
|
|
||||||
|
// We implement `sort.Interface` - `Len`, `Less`, and
|
||||||
func (this ByName) Len() int {
|
// `Swap` - on our type so we can use the `sort` package's
|
||||||
return len(this)
|
// generic `Sort` function. `Len` and `Swap`
|
||||||
}
|
// will usually be similar accross types and `Less` will
|
||||||
func (this ByName) Less(i, j int) bool {
|
// hold the actual custom sorting logic. In our case we
|
||||||
return this[i].Name < this[j].Name
|
// want to sort in order of increasing string length, so
|
||||||
}
|
// we use `len(s[i])` and `len(s[j])` here.
|
||||||
func (this ByName) Swap(i, j int) {
|
func (s ByLength) Len() int {
|
||||||
this[i], this[j] = this[j], this[i]
|
return len(s)
|
||||||
}
|
}
|
||||||
|
func (s ByLength) Swap(i, j int) {
|
||||||
type ByAge []Person
|
s[i], s[j] = s[j], s[i]
|
||||||
|
}
|
||||||
func (this ByAge) Len() int {
|
func (s ByLength) Less(i, j int) bool {
|
||||||
return len(this)
|
return len(s[i]) < len(s[j])
|
||||||
}
|
|
||||||
func (this ByAge) Less(i, j int) bool {
|
|
||||||
return this[i].Age < this[j].Age
|
|
||||||
}
|
|
||||||
func (this ByAge) Swap(i, j int) {
|
|
||||||
this[i], this[j] = this[j], this[i]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// With all of this in place, we can now implement our
|
||||||
|
// custom sort by casting the original `fruits` slice to
|
||||||
|
// `ByLength`, and then use `sort.Sort` on that typed
|
||||||
|
// slice.
|
||||||
func main() {
|
func main() {
|
||||||
kids := []Person{
|
fruits := []string{"peach", "banana", "kiwi"}
|
||||||
{"Jack", 10},
|
sort.Sort(ByLength(fruits))
|
||||||
{"Jill", 9},
|
fmt.Println(fruits)
|
||||||
{"Bob", 12},
|
|
||||||
}
|
|
||||||
fmt.Println("Original:", kids)
|
|
||||||
|
|
||||||
sort.Sort(ByName(kids))
|
|
||||||
fmt.Println("ByName: ", kids)
|
|
||||||
|
|
||||||
sort.Sort(ByAge(kids))
|
|
||||||
fmt.Println("ByAge: ", kids)
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
$ go run sorting-by-function.go
|
# Running our program shows a list sorted by string
|
||||||
Original: [{Jack 10} {Jill 9} {Bob 12}]
|
# length, as desired.
|
||||||
ByName: [{Bob 12} {Jack 10} {Jill 9}]
|
$ go run sorting-by-functions.go
|
||||||
ByAge: [{Jill 9} {Jack 10} {Bob 12}]
|
[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.
|
||||||
|
@ -30,9 +30,9 @@ func main() {
|
|||||||
for _, sourcePath := range sourcePaths {
|
for _, sourcePath := range sourcePaths {
|
||||||
foundLongLine := false
|
foundLongLine := false
|
||||||
lines := readLines(sourcePath)
|
lines := readLines(sourcePath)
|
||||||
for _, line := range lines {
|
for i, line := range lines {
|
||||||
if !foundLongLine && !todoPat.MatchString(line) && (len(line) > 58) {
|
if !foundLongLine && !todoPat.MatchString(line) && (len(line) > 58) {
|
||||||
fmt.Println("measure:", sourcePath)
|
fmt.Printf("measure: %s:%d\n", sourcePath, i+1)
|
||||||
foundLongLine = true
|
foundLongLine = true
|
||||||
foundLongFile = true
|
foundLongFile = true
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user