0
0

Go言語(Golang) sort

Posted at
package main

import (
	"fmt"
	"sort"
)

func main() {
	i := []int{5, 3, 2, 8, 7}
	s := []string{"d", "a", "f"}
	p := []struct {
		Name string
		Age  int
	}{
		{"Nancy", 20},
		{"Vera", 40},
		{"Mike", 30},
		{"Bob", 50},
	}

	// pスライスをNameフィールドでソート
	sort.Slice(p, func(i, j int) bool { return p[i].Name < p[j].Name })

	// ソートされたスライスを出力
	fmt.Println(i, s, p)
}

解説

  1. パッケージのインポート:

    import (
        "fmt"
        "sort"
    )
    
    • fmtパッケージはフォーマットされたI/Oを提供します。
    • sortパッケージはスライスやコレクションのソート機能を提供します。
  2. main関数:

    func main() {
    
    • main関数はプログラムのエントリーポイントです。
  3. スライスの定義:

    i := []int{5, 3, 2, 8, 7}
    s := []string{"d", "a", "f"}
    p := []struct {
        Name string
        Age  int
    }{
        {"Nancy", 20},
        {"Vera", 40},
        {"Mike", 30},
        {"Bob", 50},
    }
    
    • iは整数のスライスです。
    • sは文字列のスライスです。
    • pは構造体のスライスで、各要素はNameフィールドとAgeフィールドを持ちます。
  4. スライスのソート:

    sort.Slice(p, func(i, j int) bool { return p[i].Name < p[j].Name })
    
    • sort.Slice関数はスライスをソートするために使用されます。
    • 匿名関数 func(i, j int) bool はソートの基準を定義します。この場合、pスライスの要素のNameフィールドに基づいてソートします。
  5. 出力:

    fmt.Println(i, s, p)
    
    • fmt.Println関数は引数として渡された値を標準出力に表示します。
    • この場合、ソートされていない整数スライス i と文字列スライス s、およびソートされた構造体スライス p が出力されます。

実行結果 (期待されるもの)

pスライスはNameフィールドに基づいてアルファベット順にソートされます。よって、出力は次のようになります:

[5 3 2 8 7] [d a f] [{Bob 50} {Mike 30} {Nancy 20} {Vera 40}]

整数スライス i と文字列スライス s はソートされていないため、そのままの順序で出力されます。

ソートの仕組み

sort.Slice関数は内部的にソートアルゴリズム(例えば、クイックソートやマージソート)を使用します。このアルゴリズムは、要素間の大小関係を比較し、その結果に基づいて要素を並べ替えます。

比較関数の役割

ソートアルゴリズムが動作するためには、要素同士を比較する方法が必要です。Goのsort.Sliceでは、これを比較関数(less関数)によって提供します。この関数は、2つの要素のインデックスijを受け取り、それらの要素の順序を決定します。

p[i].Name < p[j].Nameの意味

具体的にこの部分:

func(i, j int) bool { return p[i].Name < p[j].Name }

は、次のように解釈されます:

  • p[i].Name < p[j].Nametrueの場合、p[i]p[j]よりも前に来るべきだと判断されます。
  • p[i].Name < p[j].Namefalseの場合、p[i]p[j]よりも後に来るべきだと判断されます。

ソートアルゴリズムの動作

ソートアルゴリズムは、この比較関数を用いて以下のように動作します:

  1. 要素の比較:

    • ソートアルゴリズムは、スライスの異なる要素のペアを選び出します。
    • 比較関数にそのペアのインデックスを渡して、どちらの要素が先に来るべきかを判断します。
  2. 要素の交換:

    • 比較関数の結果に基づいて、要素を適切な順序に並べ替えます。
    • 例えば、p[i].Name < p[j].Nametrueならば、p[i]p[j]の前に来るようにします。
  3. 繰り返し:

    • このプロセスを必要な回数だけ繰り返し、最終的に全ての要素が正しい順序に並ぶようにします。

具体例

例えば、以下のようなスライスpがあるとします:

p := []struct {
	Name string
	Age  int
}{
	{"Nancy", 20},
	{"Vera", 40},
	{"Mike", 30},
	{"Bob", 50},
}
  1. 初回比較:

    • 比較関数がp[0]("Nancy")とp[1]("Vera")を比較します。
    • p[0].Name < p[1].Name("Nancy" < "Vera")はtrueなので、順序はそのまま。
  2. 次の比較:

    • p[2]("Mike")とp[3]("Bob")を比較します。
    • p[2].Name < p[3].Name("Mike" < "Bob")はfalseなので、これらの要素を交換します。
  3. 交換後:

    • 交換後のスライスは次のようになります:
      p := []struct {
          Name string
          Age  int
      }{
          {"Nancy", 20},
          {"Vera", 40},
          {"Bob", 50},
          {"Mike", 30},
      }
      
  4. さらに比較を続ける:

    • このようにして、アルゴリズムは全ての要素ペアを比較し、適切な順序に並べ替えます。

最終的に、スライスpNameフィールドに基づいて昇順にソートされます。このように、less関数がソートアルゴリズムに対して、要素の順序を決定するための基準を提供することで、スライスが正しく並び替えられるのです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0