golang では配列をソートしたい場合に癖があり、Int や Float64、String といった固定の型であれば sort パッケージが提供する関数でソートが可能でしたが、独自の型や Int64 等といった sort パッケージが用意していない型の配列をソートするには Sorter というインタフェースを備えた型で扱うしかありませんでした。
package main
import (
"fmt"
"sort"
)
type Food struct {
Name string
Price int
}
type Foods []Food
func (f Foods) Len() int {
return len(f)
}
func (f Foods) Less(i, j int) bool {
return f[i].Price < f[j].Price
}
func (f Foods) Swap(i, j int) {
f[i], f[j] = f[j], f[i]
}
func main() {
foods := make([]Food, 3)
foods[0] = Food{Name: "みかん", Price: 150}
foods[1] = Food{Name: "バナナ", Price: 100}
foods[2] = Food{Name: "りんご", Price: 120}
sort.Sort(Foods(foods))
for _, food := range foods {
fmt.Printf("%+v\n", food)
}
}
この件に関して、GitHub の issues で多くの議論が行われました。
sort: make sorting easier, add Slice, SliceStable, SliceIsSorted, reflect.Swapper - Issue #16721 - golang/go - GitHub
Summary of problem 1. Vast majority of sort.Interface uses a slice 2. Have to define a new top level...
https://github.com/golang/go/issues/16721
僕も sort を簡単にする sorter というパッケージを公開したりもしていましたが、昨晩 sort.Slice, sort.SliceStable, sort.SliceIsSorted という3つの関数が master ブランチに入りました。
sort: add Slice, SliceStable, and SliceIsSorted - golang/go@22a2bdf - GitHub
Add helpers for sorting slices. Slice sorts slices: sort.Slice(s, func(i, j int) bool { if s[i].Foo ...
https://github.com/golang/go/commit/22a2bdfedb95612984cec3141924953b88a607b7
これにより上記のコードが以下の様にスッキリと書ける様になりました。
package main
import (
"fmt"
"sort"
)
type Food struct {
Name string
Price int
}
func main() {
foods := make([]Food, 3)
foods[0] = Food{Name: "みかん", Price: 150}
foods[1] = Food{Name: "バナナ", Price: 100}
foods[2] = Food{Name: "りんご", Price: 120}
sort.Slice(foods, func(i, j int) bool {
return foods[i].Price < foods[j].Price
})
for _, food := range foods {
fmt.Printf("%+v\n", food)
}
}
とても良いですね。SliceStable は安定ソート、SliceIsSorted はそのスライスがソート済みかどうかを返します。
まぁあるべき姿になったという感じ。