为了账号安全,请及时绑定邮箱和手机立即绑定

在go lang中按不同维度对点(结构)进行排序

在go lang中按不同维度对点(结构)进行排序

Go
慕村225694 2021-06-28 09:07:05
我有一个 Points 类型的多维点列表。我已经实现了sort.Sort接口,现在可以按y value.例如type Points []*Pointfunc (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 吗?例如,如果我按列对数据表进行排序怎么办?
查看完整描述

2 回答

?
回首忆惘然

TA贡献1847条经验 获得超11个赞

这很有趣:sort.Sort()期望类型定义排序和一些数组操作。您可以拥有“X-sortable point list”和“Y-sortable point list”类型,但让它们共享数组操作与其他语言的工作方式不同,因为 Go 不使用继承。

我想到的第一种方法是创建XSortablePointsYSortablePoints键入每个独立实现sort.InterfacePoints实例,并将您的实例转换为您目前需要的任何实例——请参见此处:http : //play.golang.org/p/9V3WlKjOwX

然后 nemo 有一个更好的方法:类型嵌入允许XSortablePointsYSortablePoints共享数组操作的功能。此外,nemo 不会将可排序类型保存在变量中,这是有道理的,因为它们只存在于这个排序调用中。这是调整后的示例代码:http : //play.golang.org/p/wNm-ilM18n

请注意,这些方法在您投射时实际上都没有复制您的点数据,只是复制了切片标题。通过查看第一个示例打印出的指针地址,您可以看到这一点。

你可以变得更有趣:在http://play.golang.org/p/4PmJVi2_7D有一个 Points.Sort 使用任意比较函数。我认为只定义更多类型的蛮力方法就可以了,只要您只有两个或三个排序,但情况会有所不同。请注意,对于比此处的点大得多的类型,您可能希望将比较器定义为采用指针而不是值,以避免复制。

re: SORT_BY_X: 我通常会避免在程序运行时更新全局模式设置变量,因为有很多方法可以反过来咬你。例如,也许有一天你会有两个并行的 goroutine,然后当它们同时访问全局时就会出现问题。或者,当 SORT_BY_X 的初始值为 时,某些代码可能会工作false,然后有一天会失败,因为它是true在另一个任务运行后留下的。如果您确实发现自己需要一个模式变量,请弄清楚您是否可以将其设为函数参数或将其附加到对象上,而不是将其设为全局变量。

最后,可能有一个包已经提供了您想要的一些更高级别的功能。例如,这里列出了一些与地理数据相关的包:https : //code.google.com/p/go-wiki/wiki/Projects#GIS


查看完整回答
反对 回复 2021-07-05
?
侃侃无极

TA贡献2051条经验 获得超10个赞

除了 user2714852 的回答之外,您还可以使用与包中已用于反向排序的技术相同的技术sort:隐藏Less()定义。


虽然这与已经提出的类似,但到达那里的方式有点不同(例如在游戏中)。你定义你的点:


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)


查看完整回答
反对 回复 2021-07-05
  • 2 回答
  • 0 关注
  • 264 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信