前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go 自定义排序

go 自定义排序

作者头像
超级大猪
发布2019-11-22 00:06:33
6360
发布2019-11-22 00:06:33
举报
文章被收录于专栏:大猪的笔记大猪的笔记

自己来排一排 sort.go

代码语言:javascript
复制
package objsort

// objsort 可以给任意的数组按key排序(like py3), 找min max,就是这么666

import (
    "fmt"
    "reflect"
    "sort"
)

func getLess(arrItem interface{}) func(i, j interface{}) bool {
    switch arrItem.(type) {
    case string:
        return func(left, right interface{}) bool {
            return left.(string) < right.(string)
        }
    case int:
        return func(left, right interface{}) bool {
            return left.(int) < right.(int)
        }
    case int8:
        return func(left, right interface{}) bool {
            return left.(int8) < right.(int8)
        }
    case int16:
        return func(left, right interface{}) bool {
            return left.(int16) < right.(int16)
        }
    case int32:
        return func(left, right interface{}) bool {
            return left.(int32) < right.(int32)
        }
    case int64:
        return func(left, right interface{}) bool {
            return left.(int64) < right.(int64)
        }
    case float32:
        return func(left, right interface{}) bool {
            return left.(float32) < right.(float32)
        }
    case float64:
        return func(left, right interface{}) bool {
            return left.(float64) < right.(float64)
        }
    case uint:
        return func(left, right interface{}) bool {
            return left.(uint) < right.(uint)
        }
    case uint8:
        return func(left, right interface{}) bool {
            return left.(uint8) < right.(uint8)
        }
    case uint16:
        return func(left, right interface{}) bool {
            return left.(uint16) < right.(uint16)
        }
    case uint32:
        return func(left, right interface{}) bool {
            return left.(uint32) < right.(uint32)
        }
    case uint64:
        return func(left, right interface{}) bool {
            return left.(uint64) < right.(uint64)
        }
    }
    panic(fmt.Sprintln("暂时不支持的类型", arrItem))
}

var Self = func(v interface{}) interface{} {
    return v
}

// 自定义的 Reverse 类型
type keySort struct {
    arrKey       []interface{}
    innerSwapper func(i, j int)
    less         func(i, j interface{}) bool
    len          int
}

func (k *keySort) Less(i, j int) bool {
    return k.less(k.arrKey[i], k.arrKey[j])
}

func (k *keySort) Swap(i, j int) {
    k.arrKey[i], k.arrKey[j] = k.arrKey[j], k.arrKey[i]
    k.innerSwapper(i, j)
}

func (k *keySort) Len() int {
    return len(k.arrKey)
}

// ByKey 可以排序arr
// arr 是任意的数组,
// key 为给定的函数,提取对象特征做排序依据,必须return int* uint* float* string
// reversed决定结果是否逆序
func ByKey(arr interface{},
    key func(interface{}) interface{}, reversed bool) {
    switch reflect.TypeOf(arr).Kind() {
    case reflect.Slice:
        s := reflect.ValueOf(arr)
        if s.Len() == 0 || s.Len() == 1 {
            return
        }

        less := getLess(key(s.Index(0).Interface()))
        swap := reflect.Swapper(arr)

        arrKey := make([]interface{}, 0)
        for i := 0; i < s.Len(); i++ {
            arrKey = append(arrKey, key(s.Index(i).Interface()))
        }

        keysort := new(keySort)
        keysort.innerSwapper = swap
        keysort.arrKey = arrKey
        keysort.less = less
        if reversed == true {
            sort.Sort(sort.Reverse(keysort))
        } else {
            sort.Sort(keysort)
        }
    }
}

func compare(arr interface{},
    key func(interface{}) interface{}, isless bool) interface{} {
    var target interface{}
    switch reflect.TypeOf(arr).Kind() {
    case reflect.Slice:
        s := reflect.ValueOf(arr)
        if s.Len() == 0 {
            return nil
        }

        target = s.Index(0).Interface()
        left := key(target)

        less := getLess(left)

        for i := 0; i < s.Len(); i++ {
            tp := s.Index(i).Interface()
            right := key(tp)
            // 判定 target 和 tp的大小关系
            // 如果isless 为 true 则 target < tp
            if less(left, right) == isless {
                target = tp
            }
        }

    }
    return target
}

func Min(arr interface{},
    key func(interface{}) interface{}) interface{} {
    return compare(arr, key, false)
}

func Max(arr interface{},
    key func(interface{}) interface{}) interface{} {
    return compare(arr, key, true)
}

main.go

代码语言:javascript
复制
package main

import (
    "fmt"
    "math"
    "math/rand"
    "objsort"
    "sort"
    "time"
)

func RndInt(start, end int) int {
    du := end - start + 1
    return start + rand.Intn(du)
}

type Point struct {
    X int
    Y int
}

func main() {
    t1 := make([]int, 0)
    t2 := make([]int, 0)

    for i := 0; i < 100000; i += 1 {
        tp := RndInt(0, 99999)
        t1 = append(t1, tp)
        t2 = append(t2, tp)
    }
    now := time.Now()
    sort.Slice(t1, func(i, j int) bool {
        return t1[i] < t1[j]
    })

    fmt.Println(time.Since(now))

    now = time.Now()
    fmt.Println(t2[:10])
    objsort.ByKey(t2, objsort.Self, false)
    fmt.Println(time.Since(now))
    fmt.Println(t2[:10])

    var arrPoint1 = []Point{
        Point{30, 60},
        Point{80, 70},
        Point{10, 65},
    }

    objsort.ByKey(arrPoint1, func(i interface{}) interface{} {
        obj := i.(Point)
        return math.Sqrt(float64(obj.X*obj.X + obj.Y*obj.Y))
    }, false)
    fmt.Println(arrPoint1)
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-02-22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档