首页 > 其他分享 >golang sort包应用

golang sort包应用

时间:2023-11-23 23:13:12浏览次数:37  
标签:sort 应用 people int fmt golang func 升序

一、sort内置排序函数

函数 作用
func Float64s(x []float64) 对float64类型的切片进行升序排序
func Float64sAreSorted(x []float64) bool 判断float64类型切片x是否按升序排序
func Ints(x []int) 对int类型的切片进行升序排序
func IntsAreSorted(x []int) bool 判断int类型切片x是否按升序排序
func SearchFloat64s(a []float64, x float64) int 切片a必须是已按升序排序,二分查找,若x存在a中,则返回a的位置,否则返回可以插入的位置,可以是len(a)
func SearchInts(a []int, x int) int 同SearchFloat64s,查找的类型为int类型切片
func SearchStrings(a []string, x string) int 同SearchFloat64s,查找切片类型为string

二、sort内置排序函数使用

  • func Float64s 和 func Float64sAreSorted
package main

import (
	"fmt"
	"math"
	"sort"
)

func main() {
	s := []float64{5.2, -1.3, 0.7, -3.8, 2.6}              // unsorted
	fmt.Println("are sorted: ", sort.Float64sAreSorted(s)) // are sorted:  false
	sort.Float64s(s)
	fmt.Println("are sorted: ", sort.Float64sAreSorted(s)) // are sorted:  true
	fmt.Println(s)                                         // [-3.8 -1.3 0.7 2.6 5.2]

	s = []float64{math.Inf(1), math.NaN(), math.Inf(-1), 0.0} // unsorted
	fmt.Println("are sorted: ", sort.Float64sAreSorted(s))    // are sorted:  false
	sort.Float64s(s)
	fmt.Println("are sorted: ", sort.Float64sAreSorted(s)) // are sorted:  true
	fmt.Println(s)                                         // [NaN -Inf 0 +Inf]

}

  • func Ints 和 func IntsAreSorted
package main

import (
	"fmt"
	"sort"
)

func main() {
	s := []int{5, 2, 6, 3, 1, 4}                     // unsorted
	fmt.Println("are sort: ", sort.IntsAreSorted(s)) //are sort:  false
	sort.Ints(s)
	fmt.Println("are sort: ", sort.IntsAreSorted(s)) //are sort:  true
	fmt.Println(s)                                   //[1 2 3 4 5 6]
}


  • func SearchFloat64s
package main

import (
	"fmt"
	"sort"
)

func main() {
	a := []float64{1.0, 2.0, 3.3, 4.6, 6.1, 7.2, 8.0} //已经按升序排好序的切片

	x := 2.0
	i := sort.SearchFloat64s(a, x) //查找存在的元素,返回元素所在的下标
	fmt.Printf("found %g at index %d in %v\n", x, i, a)
	//found 2 at index 1 in [1 2 3.3 4.6 6.1 7.2 8]

	x = 0.5
	i = sort.SearchFloat64s(a, x) //查找元素不存在,返回可以插入的位置
	fmt.Printf("%g not found, can be inserted at index %d in %v\n", x, i, a)
	//0.5 not found, can be inserted at index 0 in [1 2 3.3 4.6 6.1 7.2 8]
}

  • func SearchInts
    效果同SearchFloat64s,查找切片类型为int
package main

import (
	"fmt"
	"sort"
)


func main() {
	a := []int{1, 2, 3, 4, 6, 7, 8}

	x := 2
	i := sort.SearchInts(a, x)
	fmt.Printf("found %d at index %d in %v\n", x, i, a)

	x = 5
	i = sort.SearchInts(a, x)
	fmt.Printf("%d not found, can be inserted at index %d in %v\n", x, i, a)
}


  • func SearchStrings
package main

import (
	"fmt"
	"sort"
)

func main() {
	//已按升序排好序的切片a
	a := []string{"a", "abb", "acc", "bb", "c", "ca"}

	x := "bb"
	i := sort.SearchStrings(a, x)
	fmt.Printf("found %s at index %d in %v\n", x, i, a)
	//found bb at index 3 in [a abb acc bb c ca]

	x = "aaa"
	i = sort.SearchStrings(a, x)
	fmt.Printf("%s not found, can be inserted at index %d in %v\n", x, i, a)
	//aaa not found, can be inserted at index 1 in [a abb acc bb c ca]
}

三、自定义排序方式

sort包提供了俩种方式自定义结构类型切片排序,调用sort.Sort和sort.Slice

  • sort.Sort方式,使用sort.Sort函数,结构类型需要sort.Interface接口以提供函数调用
    • func (t type) Len() int { ... } //需要返回切片长度
    • func (t type) Less(i,j int) bool {...} //返回true, i所在元素排j在前面,false i所在元素排j在后面
    • func (t type) Swap(i, j int) {....} // 实现交换
package main

import (
	"fmt"
	"sort"
)
//自定义结构类型
type Person struct {
	Name string
	Age  int
}

func (p Person) String() string {
	return fmt.Sprintf("%s: %d", p.Name, p.Age)
}

// ByAge implements sort.Interface for []Person based on
// the Age field.
type ByAge []Person

// 实现sort.Interface 接口
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 } //按照Age升序排序

func main() {
	people := []Person{
		{"Bob", 31},
		{"John", 42},
		{"Michael", 17},
		{"Jenny", 26},
	}

	fmt.Println(people)
	//[Bob: 31 John: 42 Michael: 17 Jenny: 26]
	sort.Sort(ByAge(people))
	fmt.Println(people)
	//[Michael: 17 Jenny: 26 Bob: 31 John: 42]
}

  • sort.Slice方式 只需要传入比较函数,这种方式跟其他编程语言(python,C++...)所提供的sort排序方式类似
type Person struct {
	Name string
	Age  int
}
//使用sort.Slice 有无定义sort.Interface接口都会被忽略
func (p Person) String() string {
	return fmt.Sprintf("%s: %d", p.Name, p.Age)
}

func main() {
	people := []Person{
		{"Bob", 31},
		{"John", 42},
		{"Michael", 17},
		{"Jenny", 26},
	}
	sort.Slice(people, func(i, j int) bool {
		return people[i].Age < people[j].Age
	})
	//按照年龄升序
	fmt.Printf("%v\n", people)
	//[Michael: 17 Jenny: 26 Bob: 31 John: 42]

	people = []Person{
		{"Bob", 31},
		{"John", 42},
		{"Michael", 17},
		{"Jenny", 26},
	}
	sort.Slice(people, func(i, j int) bool {
		return people[i].Age > people[j].Age
	})
	//按照年龄降序
	fmt.Printf("%v", people)
	//[John: 42 Bob: 31 Jenny: 26 Michael: 17]
}

四、sort.Sort排序方式封装

当一个结构类型需要多种不同的排序方式时,可以封装一层ByType类型来实现比较接口 Less

package main

import (
	"fmt"
	"sort"
)

type Person struct {
	Name string
	Age  int
}

func (p Person) String() string {
	return fmt.Sprintf("%s: %d", p.Name, p.Age)
}

type Persons []*Person

// 实现sort.Interface 接口
func (p Persons) Len() int      { return len(p) }
func (p Persons) Swap(i, j int) { p[i], p[j] = p[j], p[i] }

//封装定义多种比较方式类型
// 按年龄升序方式排序
type ByAge struct{ Persons }

func (b ByAge) Less(i, j int) bool { return b.Persons[i].Age < b.Persons[j].Age }

// 按名称字典序升序
type ByName struct{ Persons }

func (b ByName) Less(i, j int) bool { return b.Persons[i].Name < b.Persons[j].Name }

func main() {
	people := []*Person{
		{"Bob", 31},
		{"John", 42},
		{"Michael", 17},
		{"Jenny", 26},
	}

	//按照年龄升序
	sort.Sort(ByAge{people})
	fmt.Printf("%v\n", people)
	//[Michael: 17 Jenny: 26 Bob: 31 John: 42]

	people = []*Person{
		{"Bob", 31},
		{"John", 42},
		{"Michael", 17},
		{"Jenny", 26},
	}

	//按照名称字典序升序排序
	sort.Sort(ByName{people})
	fmt.Printf("%v", people)
	//[Bob: 31 Jenny: 26 John: 42 Michael: 17]
}

func Search(n int, f func(int) bool) int
可以用来实现在升序序列中找到第一个大于等于或大于的元素位置(如C++中的lower_bound,upper_bound函数,或python中的bisect.bisect_left,bisect.bisect_right方法)
或者在降序队列中找到第一个小于等于或小于的元素位置

package main

import (
	"fmt"
	"sort"
)

func main() {
	a := []int{1, 2, 3, 4, 5, 6, 7}
	//在升序队列中找到第一个大于等于3的位置
	x := 3
	pos := sort.Search(len(a), func(i int) bool {
		return a[i] >= x
	})
	fmt.Println("pos ", pos) // 2

	//在升序队列中找到第一个大于3的位置
	pos = sort.Search(len(a), func(i int) bool {
		return a[i] > x
	})
	fmt.Println("pos ", pos) // 3

	//降序排序
	sort.Slice(a, func(i, j int) bool {
		return a[i] > a[j]
	})
	fmt.Println(a) //[7 6 5 4 3 2 1]
	//在降序队列中找到第一个小于等于3的位置
	pos = sort.Search(len(a), func(i int) bool {
		return a[i] <= x
	})
	fmt.Println("pos ", pos) // 4

	//在降序队列中找到第一个小于3的位置
	pos = sort.Search(len(a), func(i int) bool {
		return a[i] < x
	})
	fmt.Println("pos ", pos) // 5
}

六、逆序排序 func Reverse

这里的逆序是相对的,假如定义的升序排序,那么反转后就是降序,定义的降序,反转后就是升序

package main

import (
	"fmt"
	"sort"
)

type Person struct {
	Name string
	Age  int
}

func (p Person) String() string {
	return fmt.Sprintf("%s: %d", p.Name, p.Age)
}

type Persons []*Person

// 实现sort.Interface 接口
func (p Persons) Len() int      { return len(p) }
func (p Persons) Swap(i, j int) { p[i], p[j] = p[j], p[i] }

// 按年龄升序方式排序
type ByAge struct{ Persons }

func (b ByAge) Less(i, j int) bool { return b.Persons[i].Age < b.Persons[j].Age }

// 按名称字典序升序
type ByName struct{ Persons }

func (b ByName) Less(i, j int) bool { return b.Persons[i].Name < b.Persons[j].Name }

func main() {
	people := []*Person{
		{"Bob", 31},
		{"John", 42},
		{"Michael", 17},
		{"Jenny", 26},
	}

	//按照年龄升序 逆序后按照年龄降序
	sort.Sort(sort.Reverse(ByAge{people}))
	fmt.Printf("%v\n", people)
	//[John: 42 Bob: 31 Jenny: 26 Michael: 17]

	people = []*Person{
		{"Bob", 31},
		{"John", 42},
		{"Michael", 17},
		{"Jenny", 26},
	}

	//按照名称字典序升序排序, 逆序后按照降序排序
	sort.Sort(sort.Reverse(ByName{people}))
	fmt.Printf("%v", people)
	//[Michael: 17 John: 42 Jenny: 26 Bob: 31]
}

七、总结

  • 一般情况下int或float64类型的切片使用内置函数sort.Ints和sort.Float64s进行排序,以及使用SearchInts和SearchFloats进行查找
  • 自定义的数据类型排序可以使用sort.Sort需要定义sort.Interface接口 或者使用sort.Slice函数提供比较函数进行排序
  • 对于同种数据类型 多个不同类型排序方式,可以通过封装多个Less接口来进行实现
  • 使用Search函数可以实现C++中upper_bound和lower_bound函数二分查找功能
  • 对于已经定义的排序方式,使用sort.Reverse可以反转排序的方式

八、参考

https://pkg.go.dev/sort

标签:sort,应用,people,int,fmt,golang,func,升序
From: https://www.cnblogs.com/chen-pi/p/17852731.html

相关文章

  • P5143 攀爬者(结构体+sort排序)
    P5143攀爬者sort排序:对于数组而言sort(数组+begin,数组+stop)(左闭右开)例:sort(a+1,a+n+1)=sort(a[1]~a[n])对于结构体在数组基础上多一个cmp运用:sort(数组+begin,数组+stop,cmp)cmp本身需要定义一个函数来表示比较。#include<iostream>#include<string>#include<ma......
  • 7-2 队列应用(蓝桥杯)
    importjava.util.LinkedList;importjava.util.Queue;importjava.util.Scanner; publicclassMain{    publicstaticvoidmain(String[]args){        Scannersc=newScanner(System.in);        Queue<String>vip=newLinkedList<>();......
  • 畅谈Linux在小型微型企业中的应用
    在这篇文章里我们讨论和畅谈一下linux系统在小微型企业中的应用,为什么会写这篇文章呢?因为在平时的工作中,认识的一些做小微型企业的朋友,他们经常找我咨询或是去解决一些平时工作中的IT相关的问题,那么小微型企业中的IT环境都是都是什么样的呢?我来为大家说一下:一般的都是不超过十台......
  • BIT大数据应用算法2022年期末考试A卷解析
    北京理工大学2022年大数据应用算法期末考试A卷一、请简要回答为什么需要设计可合并的\(Sketch\)算法?可合并的\(Sketch\)算法主要是用于什么场景?解答:我谔谔二、给定数据流\(D=(1,2,5,1,4,2,3,3,2,4,5,2)\),假设\(k=3\),请详细描述\(Misra‐Gries\)算法在该数据流上的运......
  • 在vue2.0 项目中集成 Electron 实现桌面端应用
    需求:在桌面端有个应用能直接打开项目,不用在浏览器中浏览。方案:vue2.0+Electron关于vue的项目搭建和electron的相关介绍可以去官网了解,这里是直接在已经开发好的vue2.0的项目中直接加入electron。electron介绍:参考1: https://electronjs.p2hp.com/参考2:https://www.......
  • Golang学习笔记-自定义日志轮转及输出
    packagepkgimport( "fmt" "log" "log/slog" "os" "time")varcontrolLogger*slog.LoggervarfileLogger*slog.Loggerconst( timeFormat="2006-01-02")funcInitLog(filepathstring){......
  • 振弦式土压力计在岩土工程安全监测应用的方案
    振弦式土压力计在岩土工程安全监测应用的方案振弦式土压力计是一种常见的土压力测量仪器,其原理是利用振弦在土中传播的速度与土的应力状态有关的特点测量土压力。在岩土工程安全监测中,振弦式土压力计可以应用于以下方面: 1.地下连续墙和桩基工程的土压力监测:振弦式土压力计可......
  • 电脑网站支付报错“验签出错,建议检查签名字符串或私钥与应用公钥是否匹配”问题解决记
    在对接支付宝电脑网站支付的时候,遇到如下报错:“错误代码invalid-signature错误原因:验签出错,建议检查签名字符串或签名私钥与应用公钥是否匹配”。但展示的报错内容跟实际原因有所出入(在下文中有解答),这里记录下问题的解决排查过程。问题复现在对接电脑网站支付时,生成form表单......
  • nexe nodejs 应用打包工具
    nexe是类似pkg的一个nodejs应用打包工具支持的特性自包含可以用来运行多nodejsrumtime不依赖node以及npm构建幂等启动以及部署方便跨平台参考使用安装npminexe-g简单代码app.js console.log("demoapp")构建nexeapp.js说明nexe使用还是比较简单的,灵活性也很不错,值得试......
  • 第 12 节 JSON应用
    认识JSONJSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式,它基于ECMAScript的一个子集,用于存储和交换文本信息。JSON使用JavaScript的语法描述和操纵数据,但它是Python、Java、C++和其他许多编程语言的一个子集。JSON的特点:语法简单:JSON使用易于阅读的键值对形式表示数......