实现自定义排序规则

length
type Track struct {
	Title string
	Artist string
	Album string
	Year int
	Length time.Duration
}

func length(s string) time.Duration {
	d, err := time.ParseDuration(s)
	if err != nil {
		panic(s)
	}
	return d
}

样例数据如下:

var tracks = []*Track {
	{"Go", "Delilah", "From the Roots Up", 2012, length("3m38s")},
	{"Go", "Moby", "Moby", 1992, length("3m37s")},
	{"Go Ahead", "Alicia Keys", "As I Am", 2007, length("4m36s")},
}
sortInterfacesort
// 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)
}
LenLessSwap
Artist

type byArtist []*Track

func (x byArtist) Len() int {
	return len(x)
}

func (x byArtist) Less(i, j int) bool {
	return x[i].Artist < x[j].Artist;
}

func (x byArtist) Swap(i, j int) {
	x[i], x[j] = x[j], x[i]
}

之后就可以对数据进行排序:

func main() {
	//先将Track转换为定义排序规则的新类型byArtist
	sort.Sort(byArtist(tracks))
}

实现反向排序

LesssortReverse
// Reverse returns the reverse order for data.
func Reverse(data Interface) Interface {
	return &reverse{data}
}
Interfacereverse
type reverse struct {
	// This embedded Interface permits Reverse to use the methods of
	// another Interface implementation.
	Interface
}
reversereverseLess
// Less returns the opposite of the embedded implementation's Less method.
func (r reverse) Less(i, j int) bool {
	return r.Interface.Less(j, i)
}
Lessreverse
reverse := sort.Reverse(byArtist(tracks))
reverse.Lessreverse.Lenreverse.SwapreverseLenSwapbyArtistLenSwap
sort.Sort(reverse)
tracksArtist
sort.Sort(sort.Reverse(byArtist(tracks)))

利用组合实现自定义排序

前述自定义排序规则方法中,每定义一种排序规则,都要实现三个方法,其中Len和Swap方法是重复的。我们可以将要排序的Track数组和方法变量组合到一个结构体中:

type customSort struct {
	t []*Track
	less func(x, y *Track) bool
}

func (x customSort) Len() int {
	return len(x.t)
}

//Less方法调用的实际上是customSort中的Less
func (x customSort) Less(i, j int) bool {
	return x.less(x.t[i], x.t[j])
}

func (x customSort) Swap(i, j int) {
	x.t[i], x.t[j] = x.t[j], x.t[i]
}

这样我们就可以在排序的时候通过定义匿名排序函数来自定义排序规则:

	//构造customSort时定义匿名排序函数
	//注意此时匿名函数的参数为*Track
	sort.Sort(customSort{tracks, func(x, y *Track) bool {
		if x.Title != y.Title {
			return x.Title < y.Title
		}
		if x.Year != y.Year {
			return x.Year < y.Year
		}
		if x.Length != y.Length {
			return x.Length < y.Length
		}
		return false
	}})