英文:
Sort a custom struct array in GoLang
问题
如何使用GoLang对自定义结构的数组进行排序。
我的代码是:
package main
import "fmt"
type TicketDistribution struct {
Label string
TicketVolume int64
}
type TicketDistributionResponse struct {
LevelDistribution []*TicketDistribution
}
func main() {
var response TicketDistributionResponse
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "John", TicketVolume: 3})
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "Bill", TicketVolume: 7})
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "Sam", TicketVolume: 4})
for _, val := range response.LevelDistribution {
fmt.Println(*val)
}
}
这将打印输出:
{John 3}
{Bill 7}
{Sam 4}
我想按照TicketVolume值的降序对response对象进行排序。
排序后,response对象应该如下所示:
{Bill 7}
{Sam 4}
{John 3}
英文:
How do I sort a custom array of struct using GoLang.
My Code is :
package main
import "fmt"
type TicketDistribution struct {
Label string
TicketVolume int64
}
type TicketDistributionResponse struct {
LevelDistribution []*TicketDistribution
}
func main() {
var response TicketDistributionResponse
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "John", TicketVolume: 3})
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "Bill", TicketVolume: 7})
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "Sam", TicketVolume: 4})
for _, val := range response.LevelDistribution {
fmt.Println(*val)
}
}
This prints the output as
{John 3}
{Bill 7}
{Sam 4}
I want to sort the response object by TicketVolume value in descending order.
After the sort the response object should look like :
{Bill 7}
{Sam 4}
{John 3}
答案1
得分: 1
你可以使用sort.Slice
来实现。它接受你的切片和一个排序函数。
排序函数本身接受两个索引,并在左侧项小于右侧项时返回true。
通过这种方式,你可以按照自定义的条件进行排序。
package main
import (
"fmt"
"sort"
)
type TicketDistribution struct {
Label string
TicketVolume int64
}
type TicketDistributionResponse struct {
LevelDistribution []*TicketDistribution
}
func main() {
var response TicketDistributionResponse
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "John", TicketVolume: 3})
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "Bill", TicketVolume: 7})
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "Sam", TicketVolume: 4})
sort.Slice(response.LevelDistribution, func(i, j int) bool {
a := response.LevelDistribution[i]
b := response.LevelDistribution[j]
return a.TicketVolume > b.TicketVolume
})
for _, val := range response.LevelDistribution {
fmt.Println(*val)
}
}
在比较函数中使用>
可以按降序对切片进行排序,如果要按升序排序,可以使用<
。
英文:
You can use sort.Slice
for that. It takes your slice and a sort function.
The sort function itself takes two indices and returns true if the left item is smaller than the right one.
This way you can sort by your own custom criteria.
package main
import (
"fmt"
"sort"
)
type TicketDistribution struct {
Label string
TicketVolume int64
}
type TicketDistributionResponse struct {
LevelDistribution []*TicketDistribution
}
func main() {
var response TicketDistributionResponse
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "John", TicketVolume: 3})
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "Bill", TicketVolume: 7})
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "Sam", TicketVolume: 4})
sort.Slice(response.LevelDistribution, func(i, j int) bool {
a := response.LevelDistribution[i]
b := response.LevelDistribution[j]
return a.TicketVolume > b.TicketVolume
})
for _, val := range response.LevelDistribution {
fmt.Println(*val)
}
}
The use of >
in the comparison function sorts the slice descendingly, for ascending order you would use <
.
答案2
得分: 0
你可以使用slice.Interface。你可以通过定义以下三个方法来为你的结构体实现sort.Interface
接口。
type Interface interface {
// Len返回集合中的元素数量。
Len() int
// Less报告索引为i的元素是否必须在索引为j的元素之前排序。
Less(i, j int) bool
// Swap交换索引为i和j的元素。
Swap(i, j int)
}
性能:对切片进行排序 vs 对切片类型进行排序(使用Sort实现)
通用的sort.Slice()和sort.SliceStable()函数适用于任何切片。你必须将切片值作为interface{}值传递,并且实现必须使用反射(reflect包)来访问其元素和长度,并执行元素的交换。
相比之下,当你自己实现sort.Interface类型时,在你的实现中,你可以访问切片的静态类型,并且可以提供sort.Interface的实现而不使用反射,这将使其更快。
以下是更新后的代码:
package main
import (
"fmt"
"sort"
)
type TicketDistribution struct {
Label string
TicketVolume int64
}
type LevelDistribution []*TicketDistribution
func (ld LevelDistribution) Len() int {
return len(ld)
}
func (ld LevelDistribution) Swap(i, j int) {
ld[i], ld[j] = ld[j], ld[i]
}
func (ld LevelDistribution) Less(i, j int) bool {
return ld[i].TicketVolume > ld[j].TicketVolume
}
type TicketDistributionResponse struct {
LevelDistribution LevelDistribution
}
func main() {
var response TicketDistributionResponse
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "John", TicketVolume: 3})
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "Bill", TicketVolume: 7})
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "Sam", TicketVolume: 4})
ld := LevelDistribution(response.LevelDistribution)
sort.Sort(ld)
for _, val := range response.LevelDistribution {
fmt.Println(*val)
}
}
以下是基准测试的输出结果,接口/结构体方法在这里也更好:
> go test -bench=. -benchmem
goos: linux
goarch: amd64
pkg: solutions/golang/sort
cpu: 11th Gen Intel(R) Core(TM) i5-11320H @ 3.20GHz
BenchmarkWithInterface-8 5368116 191.0 ns/op 152 B/op 7 allocs/op
BenchmarkWithSlice-8 5085151 234.9 ns/op 184 B/op 8 allocs/op
PASS
英文:
You can use slice.Interface also. You can implement the sort.Interface
interface for your struct by defining these three methods.
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with index i
// must 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)
}
Performance: Sorting Slice vs Sorting Type (of Slice) with Sort implementation
> The general sort.Slice() and sort.SliceStable() functions work on any slices. You have to pass your slice value as an interface{} value, and the implementation has to use reflection (the reflect package) to access its elements and length, and to perform the swaps of elements.
> In contrast, when you implement the sort.Interface type yourself, in your implementation you have access to the static type of your slice, and you can provide the implementation of the sort.Interface without relfection, this is what will make it faster.
Here is the updated code
package main
import (
"fmt"
"sort"
)
type TicketDistribution struct {
Label string
TicketVolume int64
}
type LevelDistribution []*TicketDistribution
func (ld LevelDistribution) Len() int {
return len(ld)
}
func (ld LevelDistribution) Swap(i, j int) {
ld[i], ld[j] = ld[j], ld[i]
}
func (ld LevelDistribution) Less(i, j int) bool {
return ld[i].TicketVolume > ld[j].TicketVolume
}
type TicketDistributionResponse struct {
LevelDistribution LevelDistribution
}
func main() {
var response TicketDistributionResponse
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "John", TicketVolume: 3})
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "Bill", TicketVolume: 7})
response.LevelDistribution = append(response.LevelDistribution, &TicketDistribution{Label: "Sam", TicketVolume: 4})
ld := LevelDistribution(response.LevelDistribution)
sort.Sort(ld)
for _, val := range response.LevelDistribution {
fmt.Println(*val)
}
}
Here is the benchmark run output looks like the interface/struct method is better there too
> go test -bench=. -benchmem
goos: linux
goarch: amd64
pkg: solutions/golang/sort
cpu: 11th Gen Intel(R) Core(TM) i5-11320H @ 3.20GHz
BenchmarkWithInterface-8 5368116 191.0 ns/op 152 B/op 7 allocs/op
BenchmarkWithSlice-8 5085151 234.9 ns/op 184 B/op 8 allocs/op
PASS
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论