Go-Sort

u013344915 · · 903 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

要点

Go的Sort是对一个数据数列进行排序,但不保证stable。——关于stable,请参考数据结构或算法相关介绍。

Interface接口

要使用Sort功能,需要这个数据对象实现sort package中的接口(3个方法):

// 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)
}

这里其实隐含要求这个容器或数据集合是slice类型或Array类型。否则,没法按照索引号取值。

另外,Go的sort要实现的这个接口类似于Java的Comparable接口。C++ STL的sort则要提供一个operator<的binary function。基本思想基本是一致的,只是Go的要求更为严格。

XXXSlice & XXXs

Go的sort包已经为基本数据类型都实现了sort功能,其函数名的最后一个字母是s,表示sort之意。比如:Ints, Float64s, Strings,等等。

对应的,int、float64、string等这些基本数据类型对应的集合类似,则被命名为IntSlice、Float64Slice、StringSlice等。

只需要看源码即可了解前述内容,拷贝如下:

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

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

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

注意这里的Ints(), Sort(), IntSlice()几个函数之间的关系,并对比下面示例中的两种排序步骤。

示例

这里直接取sort_test.go中的部分代码,文件名也要符合test的命名规范,参考Go-Tesing

package main

import (
    //"fmt"
    "sort"
    "math"
    "testing"
)

var ints = [...]int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}
var float64s = [...]float64{74.3, 59.0, math.Inf(1), 238.2, -784.0, 2.3, math.NaN(), math.NaN(), math.Inf(-1), 9845.768, -959.7485, 905, 7.8, 7.8}
var strings = [...]string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"}

func TestSortIntSlice(t *testing.T) {
    data := ints
    a := sort.IntSlice(data[0:])
    sort.Sort(a)
    if !sort.IsSorted(a) {
        t.Errorf("sorted %v", ints)
        t.Errorf("   got %v", data)
    }
}

func TestSortFloat64Slice(t *testing.T) {
    data := float64s
    a := sort.Float64Slice(data[0:])
    sort.Sort(a)
    if !sort.IsSorted(a) {
        t.Errorf("sorted %v", float64s)
        t.Errorf("   got %v", data)
    }
}

func TestSortStringSlice(t *testing.T) {
    data := strings
    a := sort.StringSlice(data[0:])
    sort.Sort(a)
    if !sort.IsSorted(a) {
        t.Errorf("sorted %v", strings)
        t.Errorf("   got %v", data)
    }
}

func TestInts(t *testing.T) {
    data := ints
    sort.Ints(data[0:])
    if !sort.IntsAreSorted(data[0:]) {
        t.Errorf("sorted %v", ints)
        t.Errorf("   got %v", data)
    }
}

func TestFloat64s(t *testing.T) {
    data := float64s
    sort.Float64s(data[0:])
    if !sort.Float64sAreSorted(data[0:]) {
        t.Errorf("sorted %v", float64s)
        t.Errorf("   got %v", data)
    }
}

func TestStrings(t *testing.T) {
    data := strings
    sort.Strings(data[0:])
    if !sort.StringsAreSorted(data[0:]) {
        t.Errorf("sorted %v", strings)
        t.Errorf("   got %v", data)
    }
}

自定义数据类型

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    name string 
    age int 
}

type Persons []Person 

func (ps Persons) Len() int {
    return len(ps)
}

func (ps Persons) Less(i, j int) bool {
    return ps[i].name < ps[j].name
}

func (ps Persons) Swap(i, j int) {
    temp := ps[i]
    ps[i] = ps[j]
    ps[j] = temp
}

func main() {
    // first style
    persons := []Person{
        {"Tom", 5},
        {"Jerry", 6},
    }

    sort.Sort(Persons(persons))
    fmt.Println(persons)

    // second style
    persons2 := Persons{
        {"_Tom", 5},
        {"_Jerry", 6},
    }

    sort.Sort(persons2)
    fmt.Println(persons2)
}

有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:u013344915

查看原文:Go-Sort

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

903 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传