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

rob*_*ing 4 sorting struct go

我有一个Points类型的多维点列表.

我已经实现了sort.Sort界面,现在可以排序了y value.

例如

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
}
Run Code Online (Sandbox Code Playgroud)

现在我想用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
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法呢?我应该多次实施Less吗?如果我按列排序数据表怎么办?

two*_*two 7

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

我想到的第一个办法是创建XSortablePointsYSortablePoints每个独立实现类型sort.Interface,和你的转换Points实例,你需要哪一个的时刻-在这里看到:http://play.golang.org/p/9V3WlKjOwX.

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

请注意,这两种方法都不会在您投射时实际复制您的点数据,只是切片标题.您可以通过查看第一个示例打印出的指针地址来查看.

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

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

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

  • 现在唯一的问题是如果我也有矢量并且想要vector.sort();)我很享受go lang虽然 - 我必须编写比我通常的python一个内衬更多的代码但是我很欣赏它的速度和简单性语言中没有太多关键词. (2认同)
  • 如果您需要多个矢量排序顺序,那么传入比较函数就像[第二个例子我回去并添加](http://play.golang.org/p/Q1uOHOOT4R)可能有所帮助.在`[] Point`与`[]*Point`上,任何一个都可以工作,它可以是小对象的密切权衡:`[]*Point`涉及更多指针解除引用,`[] Point`更多复制.(另外,只有`*Point`可以是'nil`,但这样的语义不是perf.)你可以装配一个玩具程序,看看每个程序如何适用于你的任务; 根本不确定会发生什么. (2认同)

nem*_*emo 5

除了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)
}
Run Code Online (Sandbox Code Playgroud)

对于每种排序方法,您实现自己的类型,嵌入您的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
}
Run Code Online (Sandbox Code Playgroud)

现在您可以使用不同的排序方法,如下所示:

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)
Run Code Online (Sandbox Code Playgroud)

  • robert:[Effective Go](http://golang.org/doc/effective_go.html#embedding)和[规范](http://golang.org/ref/spec#Struct_types)详细介绍.如果在Nemo的代码中,你的struct的定义包含了另一种类型,如`Points`而没有为它指定一个名字,那么你的新结构会选择所有不被`XPoints` /方法隐藏的`Points`方法. `YPoints`.要访问嵌入的`Points`对象的隐藏方法或在其上使用运算符,可以通过`obj.Points`访问它 - 这就是Nemo的`points.Points [i]`在他的`Less`实现中所做的事情. (2认同)