【发布时间】:2014-04-09 08:14:02
【问题描述】:
我从 rethink 数据库中提取了一组 json 数据,然后使用 rethinkgo 将数据序列化为结构。我需要能够处理这些数据的一个子集,并根据其中一个属性的值对其进行排序。
为了避免上述问题的复杂性,我创建了一个简化的(基于水果的)示例,说明正在使用的结构以及我想要实现的目标。
package main
import (
"fmt"
"sort"
)
type Fruit struct {
AvgNumSeeds int
Name string
}
type Apple struct {
Fruit
Diameter int
}
type Banana struct {
Fruit
Length int
}
type ByNumSeeds []Apple //[]Fruit
func (p ByNumSeeds) Len() int {
return len(p)
}
func (p ByNumSeeds) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
}
func (p ByNumSeeds) Less(i, j int) bool {
return p[i].AvgNumSeeds < p[j].AvgNumSeeds
}
func main() {
apples := []Apple{
Apple{Fruit: Fruit{AvgNumSeeds: 4, Name: "Cox"}, Diameter: 10},
Apple{Fruit: Fruit{AvgNumSeeds: 6, Name: "Granny Smith"}, Diameter: 20},
Apple{Fruit: Fruit{AvgNumSeeds: 5, Name: "Pink Lady"}, Diameter: 21},
Apple{Fruit: Fruit{AvgNumSeeds: 2, Name: "Russett"}, Diameter: 15},
Apple{Fruit: Fruit{AvgNumSeeds: 1, Name: "Crab"}, Diameter: 7},
Apple{Fruit: Fruit{AvgNumSeeds: 7, Name: "Brambley"}, Diameter: 40},
Apple{Fruit: Fruit{AvgNumSeeds: 3, Name: "Braeburn"}, Diameter: 25},
}
bananas := []Banana{
Banana{Fruit: Fruit{AvgNumSeeds: 40, Name: "Lacatan"}, Length: 20},
Banana{Fruit: Fruit{AvgNumSeeds: 60, Name: "Lady Finger"}, Length: 22},
Banana{Fruit: Fruit{AvgNumSeeds: 50, Name: "Senorita"}, Length: 25},
Banana{Fruit: Fruit{AvgNumSeeds: 20, Name: "Cavendish"}, Length: 30},
Banana{Fruit: Fruit{AvgNumSeeds: 10, Name: "Goldfinger"}, Length: 27},
Banana{Fruit: Fruit{AvgNumSeeds: 70, Name: "Gros Michel"}, Length: 15},
Banana{Fruit: Fruit{AvgNumSeeds: 30, Name: "Red Dacca"}, Length: 19},
}
fmt.Println("Apples")
fmt.Printf("%+v\n\n", apples)
sort.Sort(ByNumSeeds(apples))
fmt.Printf("%+v\n\n\n", apples)
fmt.Println("Bananas")
fmt.Printf("%+v\n\n", bananas)
//sort.Sort(ByNumSeeds(bananas))
fmt.Printf("%+v\n\n", bananas)
}
http://play.golang.org/p/EjWOf58N3x
如您所见,我有两个结构,Apples 和 Bananas,它们都共享结构 Fruit 的属性;排序(包括接口函数 Len、Swap、Less)和 main 函数,它为苹果和香蕉设置数据结构,然后尝试对它们进行排序。
我对 Apples 和 Bananas 都想要的是一种(类型 ByNumSeeds、Len、Swap、Less),它能够在 Apple 和 Bananas 都从 Fruit 结构 AvgNumSeeds 共享的属性上分别排序。
我在这段代码中创建的排序将苹果切片作为其接口,并且确实按 AvgNumSeeds 对我的苹果数组进行排序。但是我无法找到一种方法让它与 Apple 和 Banana 结构一起使用。
我最初的想法是将界面视为一片水果,但可以理解的是,我得到了错误:
60: cannot convert apples (type []Apple) to type ByNumSeeds
我的下一个想法是通过某种方式将一片苹果/香蕉投射到一片水果上来解决这个错误,但这并不完全是正确的做法。
在我对解决方案的调查中,我遇到了一个名为 sortutil 的包,它有一个名为 AscByField 的函数,该函数采用结构和字段名称进行排序。我还没有尝试过,但是这个包很清楚地表明它效率不高,因为它通过使用反射来工作,并首先尝试使用标准接口方法。
有没有一种方法可以实现嵌套结构的排序,而不必为每个“子”结构类型重复排序?
【问题讨论】: