sort包主要是关于切片的排序(主要是f64、string、int类型和自定义类型的切片),默认似乎都是升序,当然作为一个非科班生,还是有一些部分没了解。
// 第一部分 函数部分
1.func Float64s(x []float64)
// 这个函数没有返回,注意
sliceFloat64 := []float64{1, 3, 1.11, 3, 4, 3, 5}
sort.Float64s(sliceFloat64)
fmt.Println(sliceFloat64) //[1 1.11 3 3 3 4 5]
2.func Float64sAreSorted(x []float64) bool
// 查看一个float64的切片是否进行了排序
sliceF64Reverse := []float64{3, 2, 1}
sliceF64 := []float64{1, 2, 3}
isSorted := sort.Float64sAreSorted(sliceF64Reverse)
isSorted2 := sort.Float64sAreSorted(sliceF64)
fmt.Println("sliceF64Reverse是否排序", isSorted) //false 也就是降序的话不承认是进行了排序
fmt.Println("sliceF64是否排序", isSorted2) //true
3.func SearchFloat64s(a []float64, x float64) int
// 该函数在a切片中寻找x,如果x和a中的某个元素相等,那么返回该元素的index,否则返回插入该元素的最佳位置
F64slice := []float64{1, 2.2, 3.3, 4.4, 5}
idx4 := sort.SearchFloat64s(F64slice, 4) //4不是以上切片的元素
fmt.Println("插入的位置是:", idx4) //插入的位置是: 3
idx4 = sort.SearchFloat64s(F64slice, 4.4) //尝试一下相同的元素会怎么放
fmt.Println("位置是:", idx4) //位置是: 3
4.func Ints(x []int)
ints := [3]int{2, 1, 3}
sort.Ints(ints[:])
fmt.Println("ints排序", ints) //ints排序 [1 2 3]
// 排序适用于切片,非要数组进行排序,可以参考上面的写法
5.func IntsAreSorted(x []int) bool
// 同Float64sAreSorted,这里就不写例子了,检查一个int类型的切片是否是升序排列
6.func SearchInts(a []int, x int) int
同SearchFloat64s,只是类型换成了int
7.func Strings(x []string)
// 该函数对string切片进行排序
strSlice := []string{"hello", "Hello", "1111", "121", "Abc", "安嘉和", "毕福剑"}
sort.Strings(strSlice)
fmt.Println("升序排列后的string:", strSlice) //[1111 121 Abc Hello hello 安嘉和 毕福剑] 从中可以看出排列规则
8.func StringsAreSorted(x []string) bool
// 该函数用于查看一个string切片是否经历过排序
// 排序规则可以参照上面一个函数
strSlice := []string{"hello", "Hello", "1111", "121", "Abc", "安嘉和", "毕福剑"}
t := sort.StringsAreSorted(strSlice)
fmt.Println("strSlice是否排序", t) //strSlice是否排序 false
9.func SearchStrings(a []string, x string) int
//查询x在a切片中的index或者是最佳插入位置,但是要注意,这个a依然必须是一个升序排序
这里的strslice借用的是上面的排序后的变量,即:[1111 121 Abc Hello hello 安嘉和 毕福剑]
idx5 := sort.SearchStrings(strSlice, "3")
fmt.Println("3的最佳插入位置是", idx5) //3的最佳插入位置是 2
10.func Search(n int, f func(int) bool) int
这一段有瑕疵,想要具体了解的可以去官网看一看
//搜寻函数,查找切片[0,n)当中符合f函数要求的一个项,返回其index,失败的话会返回数组的长度
// 建议这个数组一定要是sorted之后的
intSlice := []int{1, 2, 3, 4, 6}
idx := sort.Search(len(intSlice), func(i int) bool { return intSlice[i] >= 2 })
fmt.Println("这个index是", idx) //这个index是2
// 这个函数的使用有些奇特,若切片是升序,则后面函数中的条件最好使用>= 和>的符号,降序的话则使用<= < 的符号,这样才能得到正常结果
intSlice2 := []int{5, 3, 2, 1}
idx1 := sort.Search(len(intSlice2), func(i int) bool { return intSlice2[i] <= 1 })
fmt.Println("idx1", idx1) //idx1 3
// == 这样的结果需要单独计算
// 写一个错误的例子给大家参考
idx2 := sort.Search(len(intSlice2), func(i int) bool { return intSlice2[i] >= 1 })
fmt.Println("idx2", idx2) //idx2 0 这个结果很正常
idx3 := sort.Search(len(intSlice2), func(i int) bool { return intSlice2[i] >= 5 })
fmt.Println("idx3", idx3) //idx3 4 直接返回了错误,所以说在降序之中使用>=比较符号非常不靠谱
11.func Slice(x any, less func(i, j int) bool)
// 参数中的x实际上是[]any,只要符合less函数返回的是true,就不动你的顺序
// 这是一个客制化的函数
// 先创建一个结构体
type Person struct {
Name string
Age int
}
//创建这个结构体构成的切片
people := []Person{
{"黄烽", 19},
{"马玉", 21},
{"马玉", 33},
{"孙悟空", 33},
}
// 根据元素年龄对这个切片进行排序
sort.Slice(people, func(i, j int) bool { return people[i].Age <= people[j].Age })
fmt.Println("排序后的切片:", people) //排序后的切片: [{黄烽 19} {马玉 21} {孙悟空 33} {马玉 33}] 一个升序的切片
12.func SliceStable(x any, less func(i, j int) bool)
// 这个函数就是slice但是相同的元素不会进行操作而会略过
people1 := []Person{
{"黄烽", 19},
{"马玉", 21},
{"马玉", 33},
{"孙悟空", 33},
}
sort.SliceStable(people1, func(i, j int) bool { return people1[i].Age <= people1[j].Age })
fmt.Println("people1排序后的切片", people1) //people1排序后的切片 [{黄烽 19} {马玉 21} {孙悟空 33} {马玉 33}]
// 结果是一样的,实际上我觉得区别不大,肯能内部实现的方法有区别
13.func SliceIsSorted(x any, less func(i, j int) bool) bool
// 就是看这个客制化的切片是否经过了排序
// 我们看people的切片的name是否经过了排序
这个people借用了上面排序后的变量: [{黄烽 19} {马玉 21} {孙悟空 33} {马玉 33}]
t1 := sort.SliceIsSorted(people, func(i, j int) bool { return people[i].Name <= people[j].Name })
fmt.Println("是否按照name进行了排序", t1) //是否按照name进行了排序 false
第二部分 结构体部分
其实往后看就会知道sort包当中结构体的最大作用就是将上面的一些函数的功能变成方法
1.type Float64Slice []float64
// func (x Float64Slice) Len() int
// 返回x的长度
f64slice := sort.Float64Slice([]float64{2, 3, 1, 4, 5})
len1 := f64slice.Len()
fmt.Println("切片的长度是", len1) //切片的长度是 5
//func (x Float64Slice) Less(i, j int) bool
// 这个方法判断切片的两个元素i是否小于j
t4 := f64slice.Less(1, 2)
fmt.Println("是否需要交换位置", t4) //是否需要交换位置 false
//func (p Float64Slice) Search(x float64) int
// 作用同上面的SearchFloat64s函数,只不过将其变成了一个方法
//func (x Float64Slice) Sort()
// 对这个x进行升序排序的方法
f64slice.Sort()
fmt.Println("排序之后的切片", f64slice) //排序之后的切片 [1 2 3 4 5]
//func (x Float64Slice) Swap(i, j int)
// 将切片职中的i和j对应index的元素交换位置
f64slice.Swap(0, 1)
fmt.Println("交换位置后的切片", f64slice) //交换位置后的切片 [2 1 3 4 5]
2.type IntSlice []int
其方法和Float64Slice的名称和功能是一模一样的,这里进行省略
3.type StringSlice []string
// 嘿嘿,其方法和上面两个结构体也是一模一样的,这里也省去了
第三部分 接口
1.type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
当一个结构体拥有了以上的三种方法,我们就说其实现了sort.Interface接口(注意了这个Interface是个大写不是类型了)
// 这样来说的话,以上的StringSlice/IntSlice/Float64Slice实际上就实现了这样的接口,因而能调动一些专属的函数
1.func Sort(data Interface)
// 这个是Interface接口专属的方法,注意看这里参数的类型
sliceInt := sort.IntSlice([]int{0, 3, 4, 5, 1, 1})
sort.Sort(sliceInt)
fmt.Println("升序排序之后的sliceInt", sliceInt) //升序排序之后的sliceInt [0 1 1 3 4 5]
2.func Stable(data Interface)
// 功能相当于上面的sort函数,只是使用了一种stable的方式,当两个元素相同时,不交换其位置
3.func Reverse(data Interface) Interface
借用上面的sliceInt,即 [0 1 1 3 4 5]
aa := sort.Reverse(sliceInt)
sort.Sort(aa)
fmt.Println(aa) //&{[5 4 3 1 1 0]}
// Reverse和Sort合用才能实现倒转的效果,这里的Reverse更像是一种申明,告知Sort我要降序,
// 我觉得应该会有很多人自己去写这个sort方法,这种写法有点抽象
自己实现sort.Interface接口
// 自定义一个type
type Brand struct {
Value int
Name string
}
// 再定义一个切片type
type BrandSlice []Brand
// 给BrandSlice添加方法
func (b BrandSlice) Len() int {
return len(b)
}
func (b BrandSlice) Less(i, j int) bool {
return b[i].Value < b[j].Value
}
func (b BrandSlice) Swap(i, j int) {
b[i], b[j] = b[j], b[i]
}
brands := BrandSlice([]Brand{
{100, "adidas"},
{30, "lining"},
{70, "anta"},
})
sort.Sort(brands)
fmt.Println("按照value排序后的brands", brands) //按照value排序后的brands [{30 lining} {70 anta} {100 adidas}]
//对这个切片取反
sort.Sort(sort.Reverse(brands))
fmt.Println("反向排序的brands", brands) //反向排序的brands [{100 adidas} {70 anta} {30 lining}]
sort包是一个非常有规律的包,会有打散官网函数顺序的现象,因为是一起写的,所以在例子当中可能出现借用先前变量的行为,所以如果真的打算一个个看过去的话需要注意。sort包是一个非常有规律的包。