サンプルで学ぶ Go 言語:Sorting by Functions

コレクションを特別な順序でソートしたいことがある。 例えば、文字列を辞書順ではなく、その長さの順にソートしたいとする。 ここではそのようにソートをカスタムする方法を紹介する。

package main
import (
    "fmt"
    "sort"
)

Go で独自の関数を使ってソートするには、そのための型を定義しなければならない。 ここでは byLength という型を定義するが、これは []string の単なるエイリアスである。

type byLength []string

sort.Interface を実装する。 これは LenLessSwap の3つのメソッドを我々の型に実装するということだ。 こうすると、sort パッケージの汎用な Sort 関数を使えるようになる。 LenSwap はどの型でも似たような実装になる。 Less こそが実際にソートのやり方を決める関数である。 我々の場合、文字列の長さの昇順にしたいので、len(s[i])len(s[j]) を使って Less を実装する。

func (s byLength) Len() int {
    return len(s)
}
func (s byLength) Swap(i, j int) {
    s[i], s[j] = s[j], s[i]
}
func (s byLength) Less(i, j int) bool {
    return len(s[i]) < len(s[j])
}

ここまでの準備をすれば、あとはスライス fruitsbyLength 型に変換し、sort.Sort を呼べば、独自のソートを実装できる。

func main() {
    fruits := []string{"peach", "banana", "kiwi"}
    sort.Sort(byLength(fruits))
    fmt.Println(fruits)
}

プログラムを実行すると文字列の長さでソートされたリストが表示される。

$ go run sorting-by-functions.go 
[kiwi peach banana]

独自の型を作り、3つのインターフェースに含まれるメソッドを実装し、 sort.Sort をその型の値に呼び出すパターンを使えば、 任意の関数を使って Go のスライスをソートできる。

次の例:Panic