【golang】看一看官方包sort

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包是一个非常有规律的包。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值