Go语言中多字段排序解决方案

752 阅读2分钟

Go语言中的排序API使用起来的非常的奇怪,尤其是多字段排序的时候比较别扭。

在这里,列一下常见的解决方案。

第一种,通用解决方案,直接传参数就行。

github.com/raunakjodha…

使用方式,直接点击地址看README.md。

type multiSortExamplePerson struct {
    Name string
    Age  int
}

p1 := multiSortExamplePerson{
	Name: "Joe",
	Age:  26,
}
p2 := multiSortExamplePerson{
	Name: "Azin",
	Age:  14,
}
p3 := multiSortExamplePerson{
	Name: "Bold",
	Age:  11,
}
p4 := multiSortExamplePerson{
	Name: "AAND",
	Age:  14,
}

multisortExamplePersons := []multiSortExamplePerson{p1, p2, p3, p4}

multiSortResponse, err := MultiSorted(multisortExamplePersons, sortKeys, ascendingOrder)
if err != nil {
	fmt.Println("Failed to sort", err)
}
for i := range multiSortResponse {
	multiSortResponse[i] = multiSortResponse[i].(multiSortExamplePerson)
}
fmt.Println(multiSortResponse)
// Output: [{Joe 26} {Azin 14} {AAND 14} {Bold 11}] ```  ##### External Dependencies 1. fmt 2. reflect 3. testing 4. Sort 5. Sync

为了做的通用,源代码中使用了反射函数,效率上会慢点,在计算密集的功能不建议使用。

第二种,链式的解决方案,逐个比较,这也是Go官方给的代码片段。

go.dev/src/sort/ex…

这儿截取部分代码,

// ExampleMultiKeys demonstrates a technique for sorting a struct type using different
// sets of multiple fields in the comparison. We chain together "Less" functions, each of
// which compares a single field.
func Example_sortMultiKeys() {
	// Closures that order the Change structure.
	user := func(c1, c2 *Change) bool {
		return c1.user < c2.user
	}
	language := func(c1, c2 *Change) bool {
		return c1.language < c2.language
	}
	increasingLines := func(c1, c2 *Change) bool {
		return c1.lines < c2.lines
	}
	decreasingLines := func(c1, c2 *Change) bool {
		return c1.lines > c2.lines // Note: > orders downwards.
	}

	// Simple use: Sort by user.
	OrderedBy(user).Sort(changes)
	fmt.Println("By user:", changes)

	// More examples.
	OrderedBy(user, increasingLines).Sort(changes)
	fmt.Println("By user,<lines:", changes)

	OrderedBy(user, decreasingLines).Sort(changes)
	fmt.Println("By user,>lines:", changes)

	OrderedBy(language, increasingLines).Sort(changes)
	fmt.Println("By language,<lines:", changes)

	OrderedBy(language, increasingLines, user).Sort(changes)
	fmt.Println("By language,<lines,user:", changes)

	// Output:
	// By user: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
	// By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
	// By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}]
	// By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {r Go 100} {gri Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
	// By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]

}