5

我有一个 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
}

现在我想按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 吗?例如,如果我按列对数据表进行排序怎么办?

4

2 回答 2

7

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

我想到的第一种方法是创建XSortablePointsYSortablePoints键入每个独立实现的实例sort.Interface,并将您的Points实例转换为您目前需要的任何实例——请参见此处: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

于 2013-11-03T23:32:41.303 回答
6

除了 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)
于 2013-11-04T01:02:17.617 回答