我有一个Points类型的多维点列表。
我已经实现了sort.Sort
界面,现在可以按y value
排序。
e.g。
type Points []*Point
func (points Points) Len() int {
return len(points)
}
func (points Points) Less(i, j int) bool {
return points[i].y < points[j].y
}
func (points Points) Swap(i, j int) {
points[i], points[j] = points[j], points[i]
}
type Point struct {
x int
y int
country_id int
}
现在我想按x value
而不是y value
对点进行排序。
我的想法是使用带有全局标志的if语句(可以在排序之前打开或关闭):
func (points Points) Less(i, j int) bool {
if SORT_BY_X {
return points[i].x < points[j].x
}
return points[i].y < points[j].y
}
有更好的方法吗?我应该多次实施Less吗?如果我按列排序数据表怎么办?
答案 0 :(得分:7)
啊,这很有趣:sort.Sort()
期望类型定义排序和一些数组操作。你可以拥有“X-sortable point list”和“Y-sortable point list”类型,但是让它们共享数组ops与其他语言的工作方式不同,因为Go不使用继承。
我想到的第一种方法是创建XSortablePoints
和YSortablePoints
类型,每个类型都独立实现sort.Interface
,并将您的Points
实例转换为您需要的XSortablePoints
实例。时刻 - 见这里:http://play.golang.org/p/9V3WlKjOwX。
然后nemo有一个更好的方法:类型嵌入允许YSortablePoints
和SORT_BY_X
共享数组操作的函数。此外,nemo不会将可排序类型保存在变量中,这是有意义的,因为它们仅存在于此一个排序调用中。这是经过调整的示例代码:http://play.golang.org/p/wNm-ilM18n
请注意,这两种方法都不会在您投射时实际复制您的点数据,只是切片标题。您可以通过查看第一个示例打印出的指针地址来查看。
你可以获得更多的动力:有一个Points.Sort在http://play.golang.org/p/4PmJVi2_7D采取任意比较功能。我认为只要定义更多类型的蛮力方法就可以,只要您只有两个或三个排序,但情况会有所不同。请注意,对于比这里的点大得多的类型,您可能希望将比较器定义为采用指针而不是值,以避免复制。
re:false
:我通常会避免在程序运行时更新的全局模式设置变量,因为有很多方法可以让你回过头来咬你。例如,也许你有一天会有两个并行的goroutine,然后当它们同时访问全局时会出现问题。或者,当SORT_BY_X的初始值为true
时,某些代码可能会起作用,然后有一天会失败,因为在另一个任务运行后它被留下{{1}}。如果您确实发现自己需要一个模式变量,请确定是否可以将其作为函数参数或将其附加到对象,而不是它是全局变量。
最后,可能有一个软件包已经提供了您想要的一些更高级别的功能。例如,有一些与此处列出的地理数据相关的包:https://code.google.com/p/go-wiki/wiki/Projects#GIS
答案 1 :(得分:5)
除了user2714852的答案,你可以使用与already used相同的技巧
逆转sort
包中的排序:遮蔽Less()
定义。
虽然这与已经提出的相似,但实现目标的方式却是如此 有点不同(example on play)。你定义你的要点:
type Points []Point
func (points Points) Swap(i, j int) {
points[i], points[j] = points[j], points[i]
}
func (points Points) Len() int {
return len(points)
}
对于每种排序方法,您都可以实现嵌入Points
类型的自己的类型:
type XPoints struct {
Points
}
func (points XPoints) Less(i,j int) bool {
return points.Points[i].x < points.Points[j].x
}
type YPoints struct {
Points
}
func (points YPoints) Less(i, j int) bool {
return points.Points[i].y < points.Points[j].y
}
现在您可以使用不同的排序方法:
pts := Points{{1, 2, 3}, {2, 1, 3}}
sort.Sort(XPoints{pts})
fmt.Println("X-sorted points:", pts)
sort.Sort(YPoints{pts})
fmt.Println("Y-sorted points:", pts)