一起学go开发:数组排序

数组作为一种常见的数据结构,在实际工作中对数组的排序应用场景非常普遍,无论是php、java、还是今天要说的go,每一种语言都有其特定的实现方式。

我们学习过go语言的标准包和array的用法,我们或许已经知道,可以使用sort.Ints和sort.Slice函数进行排序,但是这个函数只能对纯数字形式的切片进行升序操作。

	var a = []int{1, 3, 2, 5, 4}

	sort.Ints(a)
	fmt.Println(a)

   现在有一份学生的成绩单,使用的是数组(或切片)形式,记录了学生的姓名:Name和考试成绩Score,需要对这份成绩单进行排序,该怎么实现呢?先来看看这份成绩单的数据结构:

type Score struct {
	name	string
	score	int
}

  我们要实现的是将StuScore按照score的大小进行升序、降序的排序。

  我们先分析sort.Ints函数是如何实现对纯数字形式的切片进行排序的,Ints函数的源码如下:

// Ints sorts a slice of ints in increasing order.
func Ints(x []int) { Sort(IntSlice(x)) }

  初看觉得很简单,对不对?让我们认真的对待这段代码:

  x是我们需要进行排序的切片,x先经过IntSlice类型的处理,后由Sort函数处理,注意:Sort的入参是一个Interface。

  先来看IntSlice的源码:

// IntSlice attaches the methods of Interface to []int, sorting in increasing order.
type IntSlice []int

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

  从IntSlice源码的注释里,我们得知,IntSlice做的事情是:把Interface的方法加入到x切片。Interface是哪个Interface?Interface有哪几个方法?Interface通常就是本包里定义的Interface,所以我们可以很容易就定位到Interface的源码,如下:

type Interface interface {
    Len() int
    Less(i int, j int) bool
    Swap(i int, j int)
}

  这个Interface也就是Sort函数要处理的。

  看到这里,我们会有一个疑问:为什么x不直接交给Sort处理,而要先经过IntSlice处理再由Sort处理?

  这样做的目的是,让x具备Len、Less、Swap这三个接口定义的方法签名,以便于交给Sort进行排序,未实现这三个方法签名的切片不具备排序的能力。

  既然知道了切片实现排序的基本原理,把我们的成绩单转换为可排序的切片,就可以实现对成绩单进行升序、降序的排序操作了。

 

  实现步骤:

  第一步:定义成绩单模型Score,并为成绩单实现Len、Less、Swap这三个方法

// Desc false默认升序,true为降序
var Desc bool

type Score struct {
   name   string
   score  int
}

type Scores []Score

func (s Scores) Len() int {
   return len(s)
}

func (s Scores) Less(i, j int) bool {
   if Desc {
      return s[i].score > s[j].score
   }
   return s[i].score < s[j].score
}

func (s Scores) Swap(i, j int) {
   s[i], s[j] = s[j], s[i]
}

  

  第二步:模拟学生成绩单

// SchoolReport 成绩单
func SchoolReport() {
   scores := Scores{
      {"alan", 95},
      {"hikerell", 91},
      {"acmfly", 96},
      {"leao", 90},
   }

   fmt.Println("Default:\n\t", scores)
   sort.Sort(scores)
   fmt.Println("IS Sorted?\n\t", sort.IsSorted(scores))
   fmt.Println("Sorted:\n\t", scores)
}

 

  第三步:分别调用升序函数、降序函数,实现对成绩单的排序操作

	student.SchoolReport()

	student.Desc = true
	student.SchoolReport()

  

  除了以上的排序方式外,还可以使用sort.Slice实现排序,代码如下:

	var desc bool

	people :=[]struct{
		Name 	string
		Age		int
	}{
		{"Gopher", 7},
		{"Alice", 55},
		{"Vera", 24},
		{"Bob", 75},
	}

	desc = true
	sort.Slice(people, func(i, j int) bool {
		if desc {
			return people[i].Age > people[j].Age
		}
		return people[i].Age < people[j].Age
	})

	fmt.Println("Sort by age:\n", people)

  

 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2023-03-09 14:30  jamstack  阅读(383)  评论(0编辑  收藏  举报