ソートは多くのアルゴリズムに不可欠な操作です。
本記事では、配列やスライスなどの要素をソートするために使われるGolangのsortパッケージについて説明します。
sortパッケージのインポート
Golangで配列やスライスをソートするには、sortパッケージをインポートする必要があります。
import "sort"
ソート関数の構文
sortパッケージのソート関数は、特定のパターンに従っています。
任意のデータ型に対して、そのデータ型のソート関数は以下のようになります。
sort.データ型s(v []データ型)
例えば、integerの場合、
sort.Ints(i []int)
スライスがソートされているかどうかを確認するための関数もあり、以下の書式で使用することができます。
sort.データ型sAreSorted(v []データ型)
例えば文字列のスライスがソートされているか確認する場合、次のようになります。
sort.StringsAreSorted(v []string)
Golangにおけるソート関数
Golangのすべてのソート関数は、昇順に並び替えたスライスを返します。
以下は、すべてのソートが動作する例です。
package main
import (
"fmt"
"sort"
)
func main() {
numbers := []int{12, 42, 55, 1, 9, 6, 3, 7, 29, 13, 72, 67, 34}
floats := []float64{24.3, 16.2, 32.9, 5.2, 1.2, 25.7, 0.9}
names := []string{"tanaka", "hojo", "oda", "asano", "kato"}
sort.Ints(numbers)
fmt.Println(numbers) // [1 3 6 7 9 12 13 29 34 42 55 67 72]
sort.Float64s(floats)
fmt.Println(floats) // [0.9 1.2 5.2 16.2 24.3 25.7 32.9]
sort.Strings(names)
fmt.Println(names) // [asano hojo kato oda tanaka]
}
ご覧のように、それぞれのデータ型にはそれに対応した関数が用意されています。
このように、任意のデータ型に対するソート関数を覚えるのが簡単なのも、Golangが提供するソートのメリットの一つですね。
スライスがソートされているかどうかをチェックする
スライスがソートされているかどうかを確認するには、その型に特化した関数を使用すればよいのです。
例えば文字列のスライスの場合、以下のような関数が使えます。
sort.StringsAreSorted(s []string)
以下は、スライスがソートされているかどうか確認する関数の使用例です。
package main
import (
"fmt"
"sort"
)
func main() {
numbers := []int{1, 2, 3, 4, 5, 6, 7}
fmt.Println(sort.IntsAreSorted(numbers)) // true
floats := []float64{2.6, 3.5, 1.9, 4.5, 9.8}
fmt.Println(sort.Float64sAreSorted(floats)) // false
names := []string{"asano", "oda", "okechi", "toyotomi", "hashiba"}
fmt.Println(sort.StringsAreSorted(names)) // false
}
独自の構造体を含むスライスをソートする
sort.Interfaceインターフェースを実装することにより、独自で定義した構造体を含むスライスをsort関数でソートすることができます。
package main
import (
"fmt"
"sort"
)
// 独自の構造体を定義
type Person struct {
Name string
Age int
}
// 上記の構造体のスライスを定義
type Persons []Person
// sort.Interfaceに含まれる関数を実装する
func (p Persons) Len() int {
return len(p)
}
func (p Persons) Less(i, j int) bool {
return p[i].Age < p[j].Age
}
func (p Persons) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
}
func main() {
// 構造体のスライスを作成する
persons := []Person{
{"織田", 19},
{"坂本", 24},
{"田中", 5},
}
// Sort関数でスライスをソートする
sort.Sort(Persons(persons))
fmt.Println(persons) // [{田中 5} {織田 19} {坂本 24}]
}
reverse関数の使い方
reverse関数はsort.Interfaceを実装しているデータであれば何でも使用でき、逆順にソートすることができます。
基本的な型については、sort.Interfaceの実装が必要ですが、このような便利な関数があるので、実装がかなり楽に済みます
sort.データ型Slice(v []データ型)
例として、数値のスライスの要素順を逆に反転する(つまり、降順にソートする)方法を解説します。
package main
import (
"fmt"
"sort"
)
func main() {
numbers := []int{12, 4, 52, 83, 70, 41, 29}
sort.Sort(sort.Reverse(sort.IntSlice(numbers))) // IntSlice関数を使用する必要がある
fmt.Println(numbers) // [83 70 52 41 29 12 4]
}