【Golang】文字列数字をソートする

f:id:suganoo:20180831184054p:plain
string型数字のスライスを小さい順にソートする方法です。

例えば、"2", "1", "11" があった場合にそのままソートしようとすると文字列ソートになってしまいますから、下記のような順序になりますね。

"1" "11" "2"

"11"が最後に来るべきですよね。

サンプルコード

下記がサンプルです。

package main

import (
        "fmt"
        "sort"
        "strconv"
)

func main() {
        str_num_list := []string{"8", "2", "10", "1", "6"}

        fmt.Printf("before : %v\n", str_num_list)

        sort.Slice(str_num_list, func(i, j int) bool {
                num_i, _ := strconv.Atoi(str_num_list[i])
                num_j, _ := strconv.Atoi(str_num_list[j])
                return num_i < num_j
        })

        fmt.Printf("after  : %v\n", str_num_list)
}
before : [8 2 10 1 6]
after  : [1 2 6 8 10]

ポイント

Slice関数

sortパッケージのSliceを見てみます。
https://golang.org/pkg/sort/#Slice

func Slice(slice interface{}, less func(i, j int) bool)

第二引数に自作のless関数を渡せばOKっすね。

なのでサンプルのようにしてます。

strconv.Atoi

strconv.Atoiは第二返却値にエラーが返されてしまうので、変数としてわざわざ確保しました。

Sliceのソース

こうなってますね。クイックソートでやってるみたい。
https://golang.org/src/sort/slice.go?#L7

func Slice(slice interface{}, less func(i, j int) bool) {
	rv := reflect.ValueOf(slice)
	swap := reflect.Swapper(slice)
	length := rv.Len()
	quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length))
}

ちなみにquickSort_funcは下記。
https://golang.org/src/sort/zfuncversion.go#136

見たところスライスの数が12以上か以下でクイックソートか挿入ソートで分けてるみたいですね。


うーんGolangは実装中身のコードまで簡単にたどれるからいいね。