代码分享 slice 排序之民间写法

stirlingx · 2020年04月03日 · 最后由 sotex 回复于 2020年09月24日 · 592 次阅读

int 升序

package main

import (
    "github.com/liyue201/gostl/algorithm/sort"
    "github.com/liyue201/gostl/ds/slice"
    "fmt"
    "math/rand"
)

func main() {
    a := make([]int, 0)
    for i := 0; i < 10; i++ {
        a = append(a, rand.Int()%20)
    }
    sort.Sort(slice.IntSlice(a).Begin(), slice.IntSlice(a).End())
    fmt.Printf("%v\n", a)
}
[0 1 8 9 10 11 11 16 17 18]

int 降序

package main

import (
    "github.com/liyue201/gostl/algorithm/sort"
    "github.com/liyue201/gostl/ds/slice"
    "fmt"
    "github.com/liyue201/gostl/utils/comparator"
    "math/rand"
)

func main() {
    a := make([]int, 0)
    for i := 0; i < 10; i++ {
        a = append(a, rand.Int()%20)
    }
    sort.Sort(slice.IntSlice(a).Begin(), slice.IntSlice(a).End(), comparator.Reverse(comparator.IntComparator))
    fmt.Printf("%v\n", a)
}

[18 17 16 11 11 10 9 8 1 0]

string 升序

package main

import (
    "fmt"
    "github.com/liyue201/gostl/algorithm/sort"
    "github.com/liyue201/gostl/ds/slice"
    "math/rand"
    "strconv"
)

func main() {
    a := make([]string, 0)
    for i := 0; i < 10; i++ {
        a = append(a, "aa"+strconv.Itoa(rand.Int()%20))
    }
    sort.Sort(slice.StringSlice(a).Begin(), slice.StringSlice(a).End())
    fmt.Printf("%v\n", a)
}

[aa0 aa1 aa10 aa11 aa11 aa16 aa17 aa18 aa8 aa9]

奇偶分开再升序排序,偶数放左边,奇数放右边

package main

import (
    "fmt"
    "github.com/liyue201/gostl/algorithm/sort"
    "github.com/liyue201/gostl/ds/slice"
    "math/rand"
)

func main() {
    a := make([]int, 0)
    for i := 0; i < 10; i++ {
        a = append(a, rand.Int()%20)
    }
    sort.Sort(slice.IntSlice(a).Begin(), slice.IntSlice(a).End(), func(a, b interface{}) int {
        va := a.(int)
        vb := b.(int)
        if va&1 < vb&1 {
            return -1
        }
        if va&1 > vb&1 {
            return 1
        }
        if va < vb {
            return -1
        }
        return 1
    })
    fmt.Printf("%v\n", a)
}
[0 8 10 16 18 1 9 11 11 17]

结构体排序

底层使用了反射,对性能要求高的场景不建议使用

package main

import (
    "fmt"
    "github.com/liyue201/gostl/algorithm/sort"
    "github.com/liyue201/gostl/ds/slice"
    "reflect"
)

type User struct {
    age  int
    name string
}

func main() {
    a := make([]*User, 0)
    a = append(a, &User{age: 2, name: "zzz"})
    a = append(a, &User{age: 5, name: "nnn"})
    a = append(a, &User{age: 2, name: "aaa"})

    sw := slice.NewSliceWrapper(a, reflect.TypeOf(&User{})) 

    // 按age排序,再按name排序
    sort.Sort(sw.Begin(), sw.End(), func(a, b interface{}) int {
        ua := a.(*User)
        ub := b.(*User)
        if ua.age < ub.age {
            return -1
        }
        if ua.age > ub.age {
            return 1
        }
        if ua.name < ub.name {
            return -1
        }
        if ua.name > ub.name {
            return 1
        }
        return 0
    })

    for i := range a {
        fmt.Printf("%+v\n", a[i])
    }
}

&{age:2 name:aaa}
&{age:2 name:zzz}
&{age:5 name:nnn}

更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio

主要是不喜欢官方的写法,官方的排序要实现 sort.Interface 接口,因为 go 没有泛型,怎么写都恶心

stirlingx 回复

确实,虽然官方 sort 包提供了常用类型切片的升序排序,但是还是挺多情况需要自己去实现 sort.Interface 接口,非常麻烦。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册