【Go】Sort 操作

Synopsis

https://golang.org/pkg/sort/

  • sort package 預設好 int, float, string 的 sort/reverse/search 等功能
  • 若要客製化,則必須
    • 自定義 Len()/Swap()/Less() 等功能,才能用 sort.Sort() 進行排序
    • 建立 type, ex:
      • type Person struct{}
      • type ByAge []Person
    • 最下方有簡易範例,但官方的 sort.Search() 是 binary search,不能用來搜尋 value
      • 錯誤範例 Playground : https://play.golang.org/p/f0E0SRNHj-5
    • 如果要搜尋 value, 則 search 必須重新制定搜尋 value 的做法
      • 上述範例若是改為 排序後->搜尋 age 即可, 如最下方範例

Int Sort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
	"fmt"
	"sort"
)

func main() {
	ints := []int{9, 3, 7, 2, 1}
	fmt.Println("Origin :", ints, "Is Ints sort? ", sort.IntsAreSorted(ints))
	sort.Ints(ints)
	fmt.Println("Sorted :", ints, "Is Ints sort? ", sort.IntsAreSorted(ints))

	// search
	fmt.Println("Find arg=3 at index :", sort.SearchInts(ints, 3))

	// reverse
	sort.Sort(sort.Reverse(sort.IntSlice(ints)))
	fmt.Println("Reverse => ", ints)
}

String Sort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

import (
	"fmt"
	"sort"
)

var names = []string{
	"max",
	"LBJ",
	"Kobe",
}

func main() {
	fmt.Println("Origin :", names, ", isSorted:", sort.StringsAreSorted(names))
	sort.Strings(names)
	fmt.Println("Sorted :", names, ", isSorted:", sort.StringsAreSorted(names))

	// search
	fmt.Println("Find 'max' at index is :", sort.SearchStrings(names, "max"))

	// reverse
	sort.Sort(sort.Reverse(sort.StringSlice(names)))
	fmt.Println("Reversed :", names)

}

Customized sort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package main

import (
	"fmt"
	"reflect"
	"sort"
)

type Person struct {
	Name string
	Age  int
}

var people = []Person{
	Person{
		Name: "zig",
		Age:  40,
	},
	Person{
		Name: "max",
		Age:  19,
	},
	Person{
		Name: "sunny",
		Age:  18,
	},
}

//
type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }

//
type ByName []Person

func (a ByName) Len() int           { return len(a) }
func (a ByName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByName) Less(i, j int) bool { return a[i].Name < a[j].Name }

func main() {
	fmt.Println(reflect.TypeOf(people))
	fmt.Println(reflect.TypeOf(ByAge(people)))
	fmt.Println(reflect.TypeOf(ByName(people)))

	fmt.Println()

	// sort age
	fmt.Println("Origin :", people)
	a := ByAge(people)
	sort.Sort(a)
	fmt.Println("Sort AGE :", a, ", isSorted?", sort.IsSorted(a))

	// sort name
	b := ByName(people)
	sort.Sort(b)
	fmt.Println("Sort NAME :", b, ", isSorted?", sort.IsSorted(b))

	// search
	obj := "sunny"
	fmt.Printf("Search Nmae = %s, and ", obj)
	i := Search(3, func(i int) bool {
		if b[i].Name == obj {
			return true
		}
		return false
	})
	if i < len(b) && b[i].Name == obj {
		fmt.Printf("found %v at %d\n", obj, i)
	} else {
		fmt.Printf("not found\n")
	}

	// reserve
	sort.Sort(sort.Reverse(b))
	fmt.Println("Reserve =>", b)
}

func Search(n int, f func(int) bool) int {
	i, j := 0, n
	for i < j {
		if !f(i) {
			i = i + 1
		} else {
			j = i
		}
	}
	return i
}