去排序一片符文?

时间:2013-08-11 10:49:48

标签: string sorting go slice rune

我无法按字符排序字符串(检查两个字符串是否为字谜,我想对它们进行排序,并检查是否相等)。

我可以像这样获得字符串[]rune的{​​{1}}表示:

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) 

那么......我如何对int32,int64或int *进行排序?

编辑:我确实对我的符文进行了排序,但男孩,这很难看。

cannot use runes (type []rune) as type []int in function argument

所以基本上如果你有一些东西,你必须将它包装在一个实现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.Interfacesort.IntSlice)。如果这真的是多么难看,那么为什么他们不在sort.Float64Slice包中提供这些WhateverSlice包装?缺乏仿制药现在开始受到严重伤害。必须有一种更好的方法来分类。

5 个答案:

答案 0 :(得分:7)

使用sort.Sort(data Interface)并实施sort.Interface,请参阅包文档中的示例。

您不能将rune int32用作int。查看int的{​​{3}}。

  

int是一个有符号整数类型,其大小至少为32位。它是一个   但是,不同的类型,而不是int32。

的别名

答案 1 :(得分:3)

实际上有一种软通用方式可以做你想要的。

查看以下包裹:

  

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

答案 2 :(得分:3)

注意:Go 1.8将引入帮助以对切片进行排序issue 16721

查看commit 22a2bdfBrad Fitzpatrick
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]
    })
}

答案 3 :(得分:2)

作为一个比较点,如果排序界面略有不同,这里的内容可能会是什么样子。也就是说,如果接口位于元素上,而不是容器上的接口,那么它会是什么样的呢?

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来满足它。但是因为它是一个界面,我们必须进行从runeComparableRune的笨拙拳击,以便动态调度可以启动:

    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的更多部分 - 更多的机制 - 而不是使用容器作为接口的方法。

答案 4 :(得分:1)

至少从2020年11月开始,https://golang.org/pkg/sort/提议使用作为闭包传递的自定义Less函数。下面的代码具有预期的效果:

package main

import (
    "fmt"
    "sort"
)

func main() {

    s1 := "eidbaooo"

    runeSlice := []rune(s1)

    fmt.Println(string(runeSlice))

    sort.Slice(runeSlice, func(i, j int) bool {
        return runeSlice[i] < runeSlice[j]
    })
    
    fmt.Println(string(runeSlice))
}

输出:

eidbaooo
abdeiooo

这可以为您省去完整的接口实现。