在GoLang中对自定义结构数组排序

fnatzsnv  于 2023-08-01  发布在  Go
关注(0)|答案(2)|浏览(123)

如何使用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}


我想对response对象按照TicketVolume值降序排序。
排序后,响应对象应该如下所示:

{Bill 7}
{Sam 4}
{John 3}

wqnecbli

wqnecbli1#

你可以使用sort.Slice来实现。它接受你的切片和一个排序函数。sort函数本身接受两个索引,如果左边的项比右边的项,则返回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)
    }
}

字符串
在comparison函数中使用>对切片进行降序排序,对于升序,您可以使用<

bgtovc5b

bgtovc5b2#

你也可以使用slice.Interface。你可以通过定义这三个方法为你的结构体实现sort.Interface接口。

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
常规的sort.Slice()和sort.SliceStable()函数可以在任何切片上工作。你必须将slice值作为interface{}值传递,实现必须使用反射(reflect包)来访问它的元素和长度,并执行元素的交换。
相反,当你自己实现sort.Interface类型时,在你的实现中你可以访问你的切片的静态类型,并且你可以提供sort.Interface的实现而不需要reflection,这会使它更快。
下面是更新后的代码

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


下面是基准测试的运行输出,看起来interface/struct方法也更好

> 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

相关问题