Go言語でソートするときは、sortパッケージを使う。
sortパッケージは、スライスやユーザーが独自に定義したコレクションをソートするプリミティブを用意している。
標準パッケージで対応している型
- float64
- int
- string
[]string(文字列のスライス)のソート
string型のスライスをソートするときには、sort.Strings
を使う。(昇順)
sort.Strings
関数は、sort.Sort(sort.StringSlice(s))
を呼んでいるだけ。
逆順にしたい場合は、sort.Reverse
を使う。
package main import ( "fmt" "sort" ) func main() { var names []string names = []string{"Ryo", "Akari", "Chen", "Eri", "Gon", "Jin", "Ken"} fmt.Printf("ソート前: %s\n", names) // ソート前: [Ryo Akari Chen Eri Gon Jin Ken] sort.Strings(names) // sort.Sort(sort.StringSlice(names)) fmt.Printf("ソート後: %s\n", names) // ソート後: [Akari Chen Eri Gon Jin Ken Ryo] // 逆順にソート sort.Sort(sort.Reverse(sort.StringSlice(names))) fmt.Printf("逆順にソート: %s\n", names) // 逆順にソート: [Ryo Ken Jin Gon Eri Chen Akari] }
Go Playground: https://play.golang.org/p/89-HDjq0zHC
[]int(数値のスライス)のソート
int型のスライスをソートするときには、sort.Ints
を使う。(昇順)
sort.Ints
関数は、sort.Sort(sort.IntSlice(s))
を呼んでいるだけ。
逆順にしたい場合は、sort.Reverse
を使う。
package main import ( "fmt" "sort" ) func main() { numbers := []int{4, 1, 2, 5, 3} fmt.Printf("ソート前: %d\n", numbers) // ソート前: [4 1 2 5 3] sort.Ints(numbers) // sort.Sort(sort.IntSlice(numbers)) fmt.Printf("ソート後: %d\n", numbers) // ソート後: ソート後: [1 2 3 4 5] // 逆順にソート sort.Sort(sort.Reverse(sort.IntSlice(numbers))) fmt.Printf("逆順にソート: %d\n", numbers) // 逆順にソート: [5 4 3 2 1] }
Go Playground: https://play.golang.org/p/XTbb9XZxjtw
[]float64(浮動小数点数のスライス)のソート
float64型のスライスをソートするときには、sort.Float64s
を使う。(昇順)
sort.Float64s
関数は、sort.Sort(sort.Float64Slice(s))
を呼んでいるだけ。
逆順にしたい場合は、sort.Reverse
を使う。
package main import ( "fmt" "sort" ) func main() { numbers := []float64{1.1, 1.4, 1.2, 1.5, 1.3} fmt.Printf("ソート前: %g\n", numbers) // ソート前: [1.1 1.4 1.2 1.5 1.3] sort.Float64s(numbers) // sort.Sort(sort.Float64Slice(numbers)) fmt.Printf("ソート後: %g\n", numbers) // ソート後: ソート後: [1.1 1.2 1.3 1.4 1.5] // 逆順にソート sort.Sort(sort.Reverse(sort.Float64Slice(numbers))) fmt.Printf("逆順にソート: %g\n", numbers) // 逆順にソート: [1.5 1.4 1.3 1.2 1.1] }
Go Playground: https://play.golang.org/p/GgUsorCj7Kg
独自のルールや型でソートする
ソートのルールを独自に実装したり、string, float64, int
以外の型のスライスをソートする場合。
2通りの方法がある。
Slice
,SliceStable
を使う。SliceStable
の場合は安定ソートとなる。Interface
を満たす型を定義して、Sort
,Stable
を使う。Stable
の場合は安定ソートとなる。
Slice, SliceStableの場合
文字列の長さ、structのフィールドでソートする例。
次のstructがあるとする。
type User struct { Name string Age int }
このAge
フィールドでソートする。
package main import ( "fmt" "sort" ) type User struct { Name string Age int } func main() { // []stringを文字数(len)が少ない順にソート languages := []string{"Ruby", "JavaScript", "Go", "PHP", "Python"} sort.Slice(languages, func(i, j int) bool { return len(languages[i]) < len(languages[j]) }) fmt.Printf("ソート後: %s\n", languages) // ソート後: [Go PHP Ruby Python JavaScript] // []Userを年齢順にソート users := []User{ {"Sato", 7}, {"Suzuki", 55}, {"Takahashi", 24}, {"Yamada", 75}, } sort.Slice(users, func(i, j int) bool { return users[i].Age < users[j].Age }) fmt.Println("ソート後:", users) // [{Sato 7} {Takahashi 24} {Suzuki 55} {Yamada 75}] }
Go Playground: https://play.golang.org/p/wLtOeDl6wN3
Sort, Stableの場合
先程と同じようにUser.Age
でソートする。
ソートしたい型のスライスに sort.Interface を実装してあげれば、sort.Sort
関数でソートできる。
type Interface interface { // Len is the number of elements in the collection. // スライスの要素数 Len() int // Less reports whether the element with // index i should sort before the element with index j. // 要素同士の比較ロジック。インデックスiの要素がインデックスjの要素の前にくるべきかどうかを判定する処理。 Less(i, j int) bool // Swap swaps the elements with indexes i and j. // インデックスiの要素とjの要素を交換する処理。 Swap(i, j int) }
実装してみるとこんな感じ。
package main import ( "fmt" "sort" ) type User struct { Name string Age int } // ByAge はsort.Interfaceの実装 type ByAge []User func (a ByAge) Len() int { return len(a) } func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age } func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func main() { // []Userを年齢順にソート users := []User{ {"Sato", 7}, {"Suzuki", 55}, {"Takahashi", 24}, {"Yamada", 75}, } sort.Sort(ByAge(users)) fmt.Println("ソート後:", users) // ソート後: [{Sato 7} {Takahashi 24} {Suzuki 55} {Yamada 75}] sort.Sort(sort.Reverse(ByAge(users))) fmt.Println("逆順ソート後:", users) // 逆順ソート後: [{Yamada 75} {Suzuki 55} {Takahashi 24} {Sato 7}] }
Go Playground: https://play.golang.org/p/aNUHPtgISe4
最初に紹介した、sort.Strings
やsort.Ints
, sort.Float64s
も同じ。
sort.Strings
の実装は、sort.Sort(sort.StringSlice(s))
を呼んでいるだけで、このsort.StringSlice
はsort.Interfaceの実装。
参考図書
Tour of Goを終えた人にオススメです!!