Go 语言问题记录——sort | 青训营

105 阅读3分钟

1. sort.Sort()

在Go语言中,方法是与特定类型关联的函数。方法可以在类型上定义,并使用该类型的值或指针进行调用。方法的接收者可以是任何自定义类型,包括结构体、基本类型的别名和接口类型。

type Float64Slice []float64

func (p Float64Slice) Sort()

Sort()是一个方法,一个和Float64Slice 类型关联的方法

自定义的类型也可以实现接口 不用一定是结构体!!!

下面是sort.go文件的源码

go/sort.go at master · golang/go (github.com) 这个链接是golang sort包在github上源码的地址

type Interface interface {  //注意 这个Interface 是接口的名字
	// Len is the number of elements in the collection.
	Len() int

	// Less reports whether the element with index i
	// must sort before the element with index j.
	//
	// If both Less(i, j) and Less(j, i) are false,
	// then the elements at index i and j are considered equal.
	// Sort may place equal elements in any order in the final result,
	// while Stable preserves the original input order of equal elements.
	//
	// Less must describe a transitive ordering:
	//  - if both Less(i, j) and Less(j, k) are true, then Less(i, k) must be true as well.
	//  - if both Less(i, j) and Less(j, k) are false, then Less(i, k) must be false as well.
	//
	// Note that floating-point comparison (the < operator on float32 or float64 values)
	// is not a transitive ordering when not-a-number (NaN) values are involved.
	// See Float64Slice.Less for a correct implementation for floating-point values.
	Less(i, j int) bool

	// Swap swaps the elements with indexes i and j.
	Swap(i, j int)
}
  

定义了一个名为Interface的接口 这个接口有三个方法 ,所以在使用sort.Sort() 的时候,需要一个声明一个结构体,然后这个结构体实现着三个方法,也就是实现Interface接口

func Sort(data Interface) {
	n := data.Len()
	if n <= 1 {
		return
	}
	limit := bits.Len(uint(n))
	pdqsort(data, 0, n, limit)
}
    

Sort() 方法要接受一个名为Interface类型的参数

e.g.

对int类型slice排序

package main
import (
    "fmt"
    "sort"
)
type IntSlice []int
func (s IntSlice) Len() int           { return len(s) }
func (s IntSlice) Less(i, j int) bool { return s[i] < s[j] }
func (s IntSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func main() {
    nums := []int{2, 3, 1, -1}
    fmt.Println("Before sorting:", nums)
    sort.Sort(IntSlice(nums))
    fmt.Println("After sorting:", nums)
}
    

对struct 类型的切片排序

package main
import (
    "fmt"
    "sort"
)
type Person struct {
    Name string
    Age  int
}
type ByAge []Person
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() {
    people := []Person{
        {"Alice", 25},
        {"Bob", 31},
        {"Charlie", 18},
        {"Dave", 42},
    }
    fmt.Println("Before sorting:")
    for _, person := range people {
        fmt.Println(person)
    }
    sort.Sort(ByAge(people))
    fmt.Println("\nAfter sorting:")
    for _, person := range people {
        fmt.Println(person)
    }
}
    

对map set进行排序

由于 Map 和 Set 是无序的数据结构,它们不支持直接使用 sort.Sort() 进行排序。需要将其转换为一个有序的数据结构(如切片),然后再使用 sort.Sort() 函数进行排序。

myMap := map[string]int{
    "b": 2,
    "c": 3,
    "a": 1,
}
keys := make([]string, 0, len(myMap))
for k := range myMap {
    keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
    fmt.Printf("Key: %s, Value: %d\n", k, myMap[k])
} 
    

2. sort.Sort()和sort.Slice()

都可以用于对切片进行排序,区别在于排序的方式和使用的灵活性

sort.Sort()函数:

sort.Sort()函数需要接收一个实现了sort.Interface接口的切片作为参数。

它对传入的切片进行原地排序,即在原始切片上进行修改。

sort.Interface接口需要实现Len()、Less()和Swap()方法。

sort.Sort()函数使用的是经典的原地排序算法,如快速排序或归并排序。

sort.Sort()函数是针对实现了sort.Interface接口的类型进行排序的,不仅仅局限于切片(slice)。实际上,sort.Sort()函数可以用于对任何实现了sort.Interface接口的类型进行排序。

sort.Slice()函数:

sort.Slice()函数接收一个切片和一个排序函数作为参数。

排序函数用于定义切片元素之间的排序规则。

它通过调用排序函数来对切片进行排序,而不需要实现sort.Interface接口。

sort.Slice()函数会根据排序函数的规则,创建一个新的切片,保持原始切片不变。

排序函数需要接收两个索引值i和j作为参数,根据切片中索引i和索引j位置的元素进行比较,并返回一个布尔值表示它们的顺序关系。

sort.Slice()函数通过传入排序函数来对切片进行排序,并返回一个新的排序后的切片