【问题标题】:How can I sort Go slices whose element type is an alias of string, but not string itself?如何对元素类型是字符串别名但不是字符串本身的 Go 切片进行排序?
【发布时间】:2015-11-18 07:13:12
【问题描述】:
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
}

【问题讨论】:

  • 顺便说一句,strings.Compare 的文档明确指出您通常不应该使用它;就做return objs[i] &lt; objs[j](或者如果抱怨,然后将它们投给string)。
  • 另外,惯用的 Swap 将是:func (p MyObjects) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
  • 有了这些简化,idiomatic way of doing it 一点也不差。
  • 经验教训:我需要写更多的 Go 才能变得更地道。

标签: sorting types go


【解决方案1】:

没有。由于 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] }

如果你真的想要这样做,你可以使用 unsafe(但请不要)。我怀疑那 3 行额外的 safe 代码是否会对您产生如此大的影响。

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

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

【讨论】:

  • p[i], p[j] = p[j], p[i] 表示法(感谢您提醒我这一点:)和紧凑的函数体将样板代码减少到最低限度,所以我会继续这样做。
【解决方案2】:

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

MyObject的底层类型与string的底层类型相同(本身就是:string),但[]MyObject的底层类型与@987654331的底层类型不同@。

在此处查看更多说明:

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)

(输出相同。)

【讨论】:

  • 我明白了。不幸的是,type MyObjects []string 不适合我。 MyObject 实例附有相当多的逻辑,所以我需要特定的类型。
猜你喜欢
  • 1970-01-01
  • 2021-03-12
  • 1970-01-01
  • 2020-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-05
相关资源
最近更新 更多