如何对Go的切片进行排序,其元素类型是字符串的别名,而不是字符串本身?

时间:2015-08-24 18:44:12

标签: sorting types go

type MyObject string
var objects []MyObject

我想对这些对象进行排序。标准库包含sort.Strings,但这需要[]string而不是[]MyObject的实例。

我目前的解决方案是实施sort.Interface(如下所示)并使用sort.Sort,但我想摆脱那个样板代码。有更好的方式吗?

type MyObjects []MyObject

func (objs MyObjects) Len() int {
    return len(objs)
}

func (objs MyObjects) Less(i, j int) bool {
    return strings.Compare(string(objs[i]), string(objs[j])) < 0
}

func (objs MyObjects) Swap(i, j int) {
    o := objs[i]
    objs[i] = objs[j]
    objs[j] = o
}

2 个答案:

答案 0 :(得分:6)

没有。由于Go不允许在切片内隐式转换类型(也没有与接口的协方差),因此您需要为您的类型提供适当的方法。

type MyObjects []MyObject

func (p MyObjects) Len() int           { return len(p) }
func (p MyObjects) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
func (p MyObjects) Less(i, j int) bool { return p[i] < p[j] }

如果真的想要这样做,你可以使用不安全(但请不要)。我怀疑这3个额外的安全代码行会对你产生很大的影响。

http://play.golang.org/p/d6ciFjjr2c

objects := []MyObject{"one", "two", "three", "four"}
sort.Strings(*(*[]string)(unsafe.Pointer(&objects)))

答案 1 :(得分:1)

IF 您的MyObject类型是“别名”,string是其基础类型,您不能。请在此处查看@JimB's answer

MyObject的基础类型与基础类型string(本身:string)相同,但基础类型[]MyObject不是与基础类型[]string相同。

请参阅此处的进一步说明:

Conversion of a slice of string into a slice of custom type

Why are you unable convert Slice types?

但如果你碰巧重构一下你的类型系统,你的问题就会消失:

type MyObjects []string

var objects MyObjects

func main() {
    objects = MyObjects{"abc", "aaa"}
    sort.Strings(objects)
    fmt.Println(objects)
}

输出(在 Go Playground 上试试):

[aaa abc]

为方便起见,如果您愿意,甚至可以在其上提供Sort()方法:

func (m MyObjects) Sort() {
    sort.Strings(m)
}

使用它:

objects = MyObjects{"abc", "aaa"}
objects.Sort()
fmt.Println(objects)

(输出相同。)