gpt4 book ai didi

go - 如何避免为类似的 golang 结构重新实现 sort.Interface

转载 作者:IT王子 更新时间:2023-10-29 01:07:13 25 4
gpt4 key购买 nike

在 Golang 中有一个问题困扰着我。假设我有 2 个结构:

type Dog struct {
Name string
Breed string
Age int
}

type Cat struct {
Name string
FavoriteFood string
Age int
}

当我尝试按 Age[]*Dog[]*Cat 进行排序时,我必须定义 2 个不同的排序结构喜欢:

type SortCat []*Cat
func (c SortCat) Len() int {//..}
func (c SortCat) Swap(i, j int) {//..}
func (c SortCat) Less(i, j int) bool {//..}

type SortDog []*Dog
func (c SortDog) Len() int {//..}
func (c SortDog) Swap(i, j int) {//..}
func (c SortDog) Less(i, j int) bool {//..}

一个自然的想法是实现一些SortableByAge 接口(interface)并使用接口(interface)函数创建一个Less 函数。喜欢:

type SortableByAge interface {
AgeValue() int
}

然后:

type SortAnimal []SortableByAge
func (c SortDog) Less(i, j int) bool {
return c[i].AgeValue() < c[j].AgeValue()
}

然而,根据: http://golang.org/doc/faq#convert_slice_of_interface

dogs := make([]*Dogs, 0 , 1)
//add dogs here
sort.Sort(SortAnimal(dogs))

以上是不可能的。

所以我想知道这个案例的最佳实践是什么

是否有任何其他技术可以减少为我错过的类似结构一次又一次地实现 sort.Interface 的需要?

编辑:我意识到我的例子很糟糕:(

在现实生活中,这两个结构非常不同,它们之间唯一的共同点是我希望通过一个共同的数值对它们进行排序。

一个更好的例子是:

type Laptop {//...}
type Pizza {//...}

这 2 个结构的唯一共同点是我希望按价格对它们的 slice (啊……在示例中不应该使用 Pizza)进行排序。

因此,在很多情况下,将它们组合成一个通用结构并不适用。但会研究 go generate。

最佳答案

这个具体案例

在这种特定情况下,您不应使用 2 种不同的类型,因为它们是相同的,只需使用常见的 Animal 类型即可:

type Animal struct {
Name string
Age int
}

func (a Animal) String() string { return fmt.Sprintf("%s(%d)", a.Name, a.Age) }

type SortAnim []*Animal

func (c SortAnim) Len() int { return len(c) }
func (c SortAnim) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c SortAnim) Less(i, j int) bool { return c[i].Age < c[j].Age }

func main() {
dogs := []*Animal{&Animal{"Max", 4}, &Animal{"Buddy", 3}}
cats := []*Animal{&Animal{"Bella", 4}, &Animal{"Kitty", 3}}

fmt.Println(dogs)
sort.Sort(SortAnim(dogs))
fmt.Println(dogs)

fmt.Println(cats)
sort.Sort(SortAnim(cats))
fmt.Println(cats)
}

输出(Go Playground):

[Max(4) Buddy(3)]
[Buddy(3) Max(4)]
[Bella(4) Kitty(3)]
[Kitty(3) Bella(4)]

一般情况

一般来说,如果您愿意放弃具体类型并改用接口(interface)类型,那么您只能使用通用的排序实现。

创建您希望 slice 包含的接口(interface)类型:

type Animal interface {
Name() string
Age() int
}

你可以有一个通用的实现:

type animal struct {
name string
age int
}

func (a *animal) Name() string { return a.name }
func (a *animal) Age() int { return a.age }
func (a animal) String() string { return fmt.Sprintf("%s(%d)", a.name, a.age) }

您的特定动物类型:

type Dog struct {
animal // Embed animal (its methods and fields)
}

type Cat struct {
animal // Embed animal (its methods and fields)
}

您在 SortAnim 上实现了 sort.Interface:

type SortAnim []Animal

func (c SortAnim) Len() int { return len(c) }
func (c SortAnim) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c SortAnim) Less(i, j int) bool { return c[i].Age() < c[j].Age() }

使用它:

dogs := SortAnim{&Dog{animal{"Max", 4}}, &Dog{animal{"Buddy", 3}}}
cats := SortAnim{&Cat{animal{"Bella", 4}}, &Cat{animal{"Kitty", 3}}}

fmt.Println(dogs)
sort.Sort(SortAnim(dogs))
fmt.Println(dogs)

fmt.Println(cats)
sort.Sort(SortAnim(cats))
fmt.Println(cats)

输出(Go Playground):

[Max(4) Buddy(3)]
[Buddy(3) Max(4)]
[Bella(4) Kitty(3)]
[Kitty(3) Bella(4)]

关于go - 如何避免为类似的 golang 结构重新实现 sort.Interface,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30336616/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com