Fragment Description:



Sorting a 'Type' based on its fields.
A common operation that makes use of the sort.Interface (a type and set of the 3 methods:
len, Swap and Less).
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 (such as a Slice, a Map key or a Map value).


sortSliceTypeOnItsFields

Go Playground

Last update, on 2015, Fri 9 Oct, 16:15:35

/* ... <== see fragment description ... */

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    name  string
    age   int
    phone string
}

// Person implements Stringer!
//
func (h Person) String() string {
    // a form of filtering
    return "{\"name\": \"" + h.name + "\", \"phone\": \"" + h.phone + "\"}"
}

// 2 types implement the sort.Interface (set of the 3 methods: len, Swap,
// Less)
// to sort []Person on its fields "phone" and "name".
//
type ByPhone []Person

func (a ByPhone) Len() int           { return len(a) }
func (a ByPhone) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByPhone) Less(i, j int) bool { return a[i].phone < a[j].phone }

type ByName []Person

func (a ByName) Len() int           { return len(a) }
func (a ByName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByName) Less(i, j int) bool { return a[i].name < a[j].name }

// The Reverse function takes a sort.Interface and returns a sort.Interface
// with a sort.Interface with an inverted Less method
//
func Reverse(data sort.Interface) sort.Interface {
    return &reverse{data}
}

type reverse struct {
    sort.Interface
}

func (r reverse) Less(i, j int) bool {
    return r.Interface.Less(j, i)
}
func main() {
    people := []Person{
        {"Alfred", 17, "+44"},
        {"Josephine", 26, "+27"},
        {"Patrick", 57, "+64"},
    }
    fmt.Printf("original: %s\n------\n", people)

    sort.Sort(ByPhone(people))
    fmt.Println("sorted by phone")
    for _, value := range people {
        // each "value" is a "person"... a Stringer,
        // fmt uses implicitly the interface as it is declared
        // interfaces are statically checked based on their declaration
        //
        fmt.Printf("\t%s\n", value)
    }
    fmt.Println("-------")
    sort.Sort(Reverse(ByPhone(people)))
    fmt.Println("reversed by phone")
    for _, value := range people {
        fmt.Printf("\t%s\n", value)
    }
    fmt.Println("-------")
    sort.Sort(ByName(people))
    fmt.Println("sorted by name")
    for _, value := range people {
        fmt.Printf("\t%s\n", value)
    }
    fmt.Println("-------")
    sort.Sort(Reverse(ByName(people)))
    fmt.Println("reversed by name")
    for _, value := range people {
        fmt.Printf("\t%s\n", value)
    }
    fmt.Println("-------")
}



Comments