RosettaCodeData/Task/Optional-parameters/Go/optional-parameters-4.go

94 lines
2.0 KiB
Go

package main
import (
"fmt"
"sort"
)
type cell string
type row []cell
type table struct {
rows []row
column int
less func(cell, cell) bool
}
func (c cell) String() string {
return fmt.Sprintf("%q", string(c))
}
func (t table) printRows(heading string) {
fmt.Println("--", heading)
for _, row := range t.rows {
fmt.Println(row)
}
fmt.Println()
}
// sort.Interface
func (t table) Len() int { return len(t.rows) }
func (t table) Swap(i, j int) { t.rows[i], t.rows[j] = t.rows[j], t.rows[i] }
func (t table) Less(i, j int) bool {
return t.less(t.rows[i][t.column], t.rows[j][t.column])
}
// struct implements named parameter-like capability
type spec struct {
ordering func(cell, cell) bool
column int
reverse bool
}
func (t *table) sort(s spec) {
// set up column and comparison function for sort
t.column = s.column
switch {
case s.ordering != nil:
t.less = s.ordering
case s.reverse:
t.less = func(a, b cell) bool { return a > b }
default:
t.less = func(a, b cell) bool { return a < b }
}
// sort
sort.Sort(t)
// reverse if necessary
if s.ordering == nil || !s.reverse {
return
}
last := len(t.rows) - 1
for i := last / 2; i >= 0; i-- {
t.rows[i], t.rows[last-i] = t.rows[last-i], t.rows[i]
}
}
func main() {
t := table{rows: []row{
{"pail", "food"},
{"pillbox", "nurse maids"},
{"suitcase", "airedales"},
{"bathtub", "chocolate"},
{"schooner", "ice cream sodas"},
}}
t.printRows("song")
// no "parameters"
t.sort(spec{})
t.printRows("sorted on first column")
// "named parameter" reverse.
t.sort(spec{reverse: true})
t.printRows("reverse sorted on first column")
// "named parameters" column and ordering
t.sort(spec{
column: 1,
ordering: func(a, b cell) bool { return len(a) > len(b) },
})
t.printRows("sorted by descending string length on second column")
}