天天看點

Golang sort排序

在程式開發中,不可避免的需要給資料集進行排序,如果在語言級别不提供支援的話,我們則需要自己寫算法進行資料的處理,麻煩還不一定高效。

幸好Golang在标準包中,官方有提供sort包中Sort()函數提供排序功能。并且天然支援[]int,[]float64,[]string切片的排序查找功能,并且也能夠實作對自定義類型集合的排序。

下面我們先來看下golang中Sort函數的結構是什麼樣的。

func Sort(data Interface) {
	n := data.Len()
	quickSort(data, 0, n, maxDepth(n))
}
           

可以看到,該函數接收的唯一的參數就是待排序集合,該集合應是一個Interface,而我們如果需要讓自定義類型的集合能夠被排序,則需要實作該interface以保證類型一緻。該接口中有三個方法:

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.
	Less(i, j int) bool
	// Swap swaps the elements with indexes i and j.
	Swap(i, j int)
}
           

資料集合實作了這三個方法後,就可以使用該包的Sort()函數進行排序。

1.1讓我們來看一個以學生年齡排序的小案例:

type Stu []student

func main() {
	var students = make(Stu, 0)
	for i := 0; i < 10; i++ {
		stu := student{
			name: strconv.Itoa(i) + "~~",
			age:  i,
		}
		students = append(students, stu)
	}
	for _, item := range students {
		fmt.Println(item.name, "--", item.age)
	}
	sort.Sort(students)
	fmt.Println("is sorted? ", sort.IsSorted(students)) //可以檢測是否已經排序
	for _, item := range students {
		fmt.Println(item.name, "--", item.age)
	}
}

func (s Stu) Len() int { //傳回集合的長度
	return len(s)
}

//Less 被定義為:i 在 j前面為true;是以我們比較i < j 是否為 true,
//i < j = false,表示i放在後面,是以目前是降序
func (s Stu) Less(i, j int) bool { //用來決定是升序還是降序
	return s[i].age > s[j].age
}

func (s Stu) Swap(i, j int) { //改變資料在集合中的位置
	s[i], s[j] = s[j], s[i]
}


type student struct {
	name string
	age  int
}
           

在Less方法中,我使用的是int類型的年齡來進行降序排列的,如果需要升序隻需要變成 < 号即可:

func (s Stu) Less(i, j int) bool {
	return s[i].age < s[j].age
}
           

1.2最後再來個基本int型的使用案例

在sort包中,給[]int排序的方法是IntSlice,結構如下:

type IntSlice []int

func (p IntSlice) Len() int           { return len(p) }
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p IntSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// Sort is a convenience method.
func (p IntSlice) Sort() { Sort(p) }
           

可以看到,該[]int也實作了Sort函數中的接口,并且有一個Sort()方法,是以我們可以這樣使用:

var nums = []int{1, 3, 2, 5, 3, 65, 3}
sort.IntSlice(nums).Sort()
           

如果我們不想這麼麻煩,sort包為我們提供了一個Ints方法,調用該方法可以直接排序:

var nums = []int{1, 3, 2, 5, 3, 65, 3}
sort.Ints(nums)
fmt.Println(nums)
           

輸出結果:

[1 2 3 3 3 5 65]

如果需要改變排序方式的話,包中同樣有提供一個Reverse方法:

func Reverse(data Interface) Interface {
	return &reverse{data}
}
           

我們看到,Reverse函數跟Sort函數接收同樣的方法,是以我們的排序時需要使用實作了那三個方法的IntSlice方法,使用方式:

sort.Sort(sort.Reverse(sort.IntSlice(nums)))
           

劇終!