我无法按字符排序字符串(检查两个字符串是否为字谜,我想对它们进行排序,并检查是否相等)。
我可以得到一个 []rune
字符串的表示 s
喜欢这个:
runes := make([]rune, len(s))
copy(runes, []rune(s))
我可以像这样排序
someInts := []int{5, 2, 6, 3, 1, 4} // unsorted
sort.Ints(someInts)
但 rune
只是一个别名 int32
所以我应该可以打电话
sort.Ints(runes)
但是,我得到错误:
cannot use runes (type []rune) as type []int in function argument
那么......我如何对int32,int64或int *进行排序?
编辑:我确实把我的符文分类了,但男孩,这很难看。
type RuneSlice []rune
func (p RuneSlice) Len() int { return len(p) }
func (p RuneSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p RuneSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func sorted(s string) string {
runes := []rune(s)
sort.Sort(RuneSlice(runes))
return string(runes)
}
所以基本上如果你有一些东西,你必须将它包装在一个实现的类型中 sort.Interface
。所有这些实现都将具有完全相同的方法体(如 sort.IntSlice
和 sort.Float64Slice
)。如果这真的是多么难看,那么为什么他们不提供这些WhateverSlice包装 sort
包?缺乏仿制药现在开始受到非常严重的伤害。必须有更好的方法来分类。
使用 sort.Sort(data Interface)
并实施 sort.Interface
,请参阅包文档中的示例。
你不能用 rune
是的 int32
如 int
。检查 评论 的 int
。
int是有符号整数类型,其大小至少为32位。它是一个
但是,不同的类型,而不是int32的别名。
实际上有一个 软通用 做你想做的事。
查看以下包:
https://github.com/BurntSushi/ty/tree/master/fun
特别是以下文件:
https://github.com/BurntSushi/ty/blob/master/fun/sort_test.go
如何使用的示例:
tosort := []int{10, 3, 5, 1, 15, 6}
fun.Sort(func(a, b int) bool {
return b < a
}, tosort)
通过该包中的反射实现了许多其他有趣的通用算法。
所有学分都去了 @BurntSushi。
作为一个比较点,如果排序界面略有不同,这里的内容可能会是什么样子。也就是说,而不是界面上 容器,如果界面在上面会是什么样子 分子 代替?
package main
import (
"fmt"
"sort"
)
type Comparable interface {
LessThan(Comparable) bool
}
type ComparableSlice []Comparable
func (c ComparableSlice) Len() int {
return len(c)
}
func (c ComparableSlice) Less(i, j int) bool {
return c[i].LessThan(c[j])
}
func (c ComparableSlice) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
}
func SortComparables(elts []Comparable) {
sort.Sort(ComparableSlice(elts))
}
//////////////////////////////////////////////////////////////////////
// Let's try using this:
type ComparableRune rune
func (r1 ComparableRune) LessThan(o Comparable) bool {
return r1 < o.(ComparableRune)
}
func main() {
msg := "Hello world!"
comparables := make(ComparableSlice, len(msg))
for i, v := range msg {
comparables[i] = ComparableRune(v)
}
SortComparables(comparables)
sortedRunes := make([]rune, len(msg))
for i, v := range comparables {
sortedRunes[i] = rune(v.(ComparableRune))
}
fmt.Printf("result: %#v\n", string(sortedRunes))
}
在这里,我们定义一个 Comparable
接口,我们得到我们的类型 ComparableRune
满足它。但因为它是一个界面,我们必须做尴尬的拳击来 rune
至 ComparableRune
这样动态调度可以启动:
comparables := make(ComparableSlice, len(msg))
for i, v := range msg {
comparables[i] = ComparableRune(v)
}
并取消装箱以取回我们的符文:
sortedRunes := make([]rune, len(msg))
for i, v := range comparables {
sortedRunes[i] = rune(v.(ComparableRune))
}
这种方法似乎要求我们知道如何在接口和值的动态类型之间来回进行类型转换。看起来我们需要使用Go的更多部分 - 更多的机制 - 而不是使用容器作为接口的方法。
注意:去1.8会 引入帮助器来分类切片。
看到 问题16721 和 提交22a2bdf 通过 布拉德菲茨帕特里克
var strings = [...]string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"}
func TestSlice(t *testing.T) {
data := strings
Slice(data[:], func(i, j int) bool {
return data[i] < data[j]
})
}