# 模仿 Go Sort 排序接口实现的自定义排序

Donne · · 2417 次点击 · · 开始浏览

Go 语言对于类型的要求非常严格，导致我们无法声明一个 `interface` 类型的切片对其排序。所以这里模仿 Go 的 sort 排序扩展包，实现对某个特定类型排序的方法。

## Interface 接口

``````// A type, typically a collection, that satisfies sort.Interface can be
// sorted by the routines in this package. The methods require that the
// elements of the collection be enumerated by an integer index.
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with
// index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}``````

## 自定义排序的结构体

``````type Student struct {
Name  string
Score int
}
type Students []Student``````

## 实现排序的接口

``````func (s Students) Len() int {
return len(s)
}

// 在比较的方法中，定义排序的规则
func (s Students) Less(i, j int) bool {
if s[i].Score < s[j].Score {
return true
} else if s[i].Score > s[j].Score {
return false
} else {
return s[i].Name < s[i].Name
}
}

func (s Students) Swap(i, j int) {
temp := s[i]
s[i] = s[j]
s[j] = temp
}``````

## 实现排序逻辑

Go 提供了基于快排实现的排序方法，这里为了体验为什么 Go 这么定义 Interface 接口，我使用了选择排序的方法代替 Go 的快排。

``````func Sort(s sort.Interface) {
length := s.Len()
for i := 0; i < length; i++ {
minIndex := i
for j := i + 1; j < length; j++ {
if s.Less(j, i) {
minIndex = j
}
}
s.Swap(minIndex, i)
}
}``````

## 重写输出

``````func (s Student) String() string {
return fmt.Sprintf("Student: %s %v", s.Name, s.Score)
}``````

## 测试输出

``````func main() {
arr := []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1}
SelectionSort(arr, len(arr))

fmt.Println(arr)

students := student.Students{}

students = append(students, student.Student{"D", 90})
students = append(students, student.Student{"C", 100})
students = append(students, student.Student{"B", 95})
students = append(students, student.Student{"A", 95})
Sort(students)

for _, student := range students {
fmt.Println(student)
}
}``````

``````[1 2 3 4 5 6 7 8 9 10]
Student: D 90
Student: A 95
Student: B 95
Student: C 100``````

0 回复

• 请尽量让自己的回复能够对别人有帮助
• 支持 Markdown 格式, **粗体**、~~删除线~~、``单行代码``
• 支持 @ 本站用户；支持表情（输入 : 提示），见 Emoji cheat sheet
• 图片支持拖拽、截图粘贴等方式上传

Go 语言对于类型的要求非常严格，导致我们无法声明一个 `interface` 类型的切片对其排序。所以这里模仿 Go 的 sort 排序扩展包，实现对某个特定类型排序的方法。

## Interface 接口

``````// A type, typically a collection, that satisfies sort.Interface can be
// sorted by the routines in this package. The methods require that the
// elements of the collection be enumerated by an integer index.
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with
// index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}``````

## 自定义排序的结构体

``````type Student struct {
Name  string
Score int
}
type Students []Student``````

## 实现排序的接口

``````func (s Students) Len() int {
return len(s)
}

// 在比较的方法中，定义排序的规则
func (s Students) Less(i, j int) bool {
if s[i].Score < s[j].Score {
return true
} else if s[i].Score > s[j].Score {
return false
} else {
return s[i].Name < s[i].Name
}
}

func (s Students) Swap(i, j int) {
temp := s[i]
s[i] = s[j]
s[j] = temp
}``````

## 实现排序逻辑

Go 提供了基于快排实现的排序方法，这里为了体验为什么 Go 这么定义 Interface 接口，我使用了选择排序的方法代替 Go 的快排。

``````func Sort(s sort.Interface) {
length := s.Len()
for i := 0; i < length; i++ {
minIndex := i
for j := i + 1; j < length; j++ {
if s.Less(j, i) {
minIndex = j
}
}
s.Swap(minIndex, i)
}
}``````

## 重写输出

``````func (s Student) String() string {
return fmt.Sprintf("Student: %s %v", s.Name, s.Score)
}``````

## 测试输出

``````func main() {
arr := []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1}
SelectionSort(arr, len(arr))

fmt.Println(arr)

students := student.Students{}

students = append(students, student.Student{"D", 90})
students = append(students, student.Student{"C", 100})
students = append(students, student.Student{"B", 95})
students = append(students, student.Student{"A", 95})
Sort(students)

for _, student := range students {
fmt.Println(student)
}
}``````

``````[1 2 3 4 5 6 7 8 9 10]
Student: D 90
Student: A 95
Student: B 95
Student: C 100``````