在lang中按不同维度排序点(结构) [英] sort points (structs) by different dimensions in go lang

查看:153
本文介绍了在lang中按不同维度排序点(结构)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我已经实现了 sort.Sort 接口,现在可以通过 y value



例如

 类型Points [] * Point 

func(points Points)Len()int {
return len(points)
}
func(points Points)Less(i,j int)bool {
return points [i] .y<点[j] .y
}
func(points Points)交换(i,j int){
points [i],points [j] = points [j],points [i ]
}

类型点结构{
x int
y int
country_id int
}

现在我想按 x值而不是 y值



我的想法是使用带有全局标志的if语句(可以在排序前打开或关闭):



  func(points Points)Less(i,j int)bool {
如果SORT_BY_X {
return points [ i] .x<点[j] .x
}
返回点[i] .y<点[j] .y
}

有没有更好的方法来做到这一点?我应该实施更少的多次?如果我按列排序数据表怎么办?

期望类型定义一个排序和一些数组操作。你可以拥有X-sortable point list和Y-sortable point list类型,但是让它们共享数组op的工作方式与其他语言的工作方式不同,因为Go不使用继承。



我想到的第一种方法是创建 XSortablePoints YSortablePoints 类型,每个类型独立实现 sort.Interface ,并将您的 Points 实例转换为此时需要的任何一个 - 请参阅: http://play.golang.org/p/9V3WlKjOwX 。然后nemo有一个更好的方法:类型嵌入允许 XSortablePoints YSortablePoints $ b

c $ c>来共享阵列操作的功能。另外,nemo不会将可排序类型保存在一个变量中,这是有意义的,因为它们只存在于这种排序调用中。以下是调整后的示例代码: http://play.golang.org/p/wNm-ilM18n



请注意,这些方法在投射时都不会复制您的点数据,而只是切片标题。你可以通过查看第一个例子打印的指针地址来看到它。



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

re: SORT_BY_X :我通常会避免在程序运行时更新的全局模式设置变量,因为有很多方法可以让你回来咬你。例如,也许你有一天会有两个并行的goroutines,然后当他们同时访问全局时发生麻烦。或者,当SORT_BY_X的初始值为 false 时,某些代码可以工作,然后有一天会失败,因为它之后剩下 true 另一项任务跑了。如果你发现自己需要一个模式变量,那么应该弄清楚它是不是全局的,你可以把它作为一个函数参数或者将它附加到一个对象上。



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


I have a list of multidimensional points of type Points.

I've implemented the sort.Sort interface and can now sort by 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
}

Now I want to sort my points by x value instead of y value.

My idea is to use an if statement with a global flag (which can be switched on or off before sorting):

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
}

Is there a better way of doing this? Should I be implementing Less multiple times? What if I was sorting tables of data by columns for example?

解决方案

Ah, this is interesting: sort.Sort() expects the type to define an ordering and some array operations. You can have "X-sortable point list" and "Y-sortable point list" types, but making them share the array ops works differently from in other languages because Go doesn't use inheritance.

The first way I thought of is to create XSortablePoints and YSortablePoints types that each independently implement sort.Interface, and convert your Points instance to whichever one you need at the moment--see here: http://play.golang.org/p/9V3WlKjOwX.

Then nemo had a better way: type embedding allows XSortablePoints and YSortablePoints to share the functions for array operations. Also, nemo doesn't save the sortable types in a variable, which makes sense as they only exist for this one sort call. Here's adjusted sample code: http://play.golang.org/p/wNm-ilM18n

Note that neither of these approaches actually copies your point data when you cast, just the slice header. You can see that by looking at the pointer addresses printed out by the first example.

You can get fancier: there's a Points.Sort taking an arbitrary comparison function at http://play.golang.org/p/4PmJVi2_7D. I think the brute-force approach of just defining more types is fine as long as you only have two or three orderings, but situations vary. Note that for types much bigger than the points here, you might want to define the comparer to take pointers rather than values, to avoid copying.

re: SORT_BY_X: I'd generally avoid global mode-setting variables that you update as the program runs, because there are lots of ways those can come back to bite you. For example, maybe you'll have two parallel goroutines someday and then trouble happens when they both access the global at once. Or maybe some code will work when the initial value of SORT_BY_X is false, then someday fail because it was left true after another task ran. If you do find yourself needing a mode variable, figure out if, instead of it being global, you could make it a function parameter or attach it to an object.

Finally, there might be a package that already provides some of the higher-level functionality you want. For example, there are some packages related to geographic data listed here: https://code.google.com/p/go-wiki/wiki/Projects#GIS

这篇关于在lang中按不同维度排序点(结构)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆