专栏首页大猪的笔记go 自定义排序

go 自定义排序

自己来排一排 sort.go

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

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)
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python笔记:类型检验

    函数注解可以用内置方法获取,所以可以利用这个特性做一个类型检验的装饰器。 代码如下:

    超级大猪
  • Python笔记:装饰器(面向切面)

    http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html

    超级大猪
  • rxgo笔记

    超级大猪
  • golang学习之接口型函数

    先说下使用接口型函数的好处: 1、不必将某个接口函数附在某个type上面,保证了命名随意 2、 可以直接调用函数或者使用该接口,两两不耽误 直接上代码吧: //...

    用户1141560
  • Flutter布局篇(1)--水平和垂直布局详解

    本文版权归作者AWeiLoveAndroid所有,未经授权,严禁私自转载。转载请声明原文链接和作者信息。

    AWeiLoveAndroid
  • 分治策略之最大子数组(Python实现)

    一个整数数组中的元素有正有负,在该数组中找出一个连续子数组,要求该连续子数组中各元素的和最大,这个连续子数组便被称作最大连续子数组。

    TrueDei
  • startUML怎么画interface接口 原

                                                                          图1 

    克虏伯
  • 【HTB系列】靶机Teacher的渗透测试详解

    第一个img元素多了一个onerror错误事件,意思是加载错误时在控制台输出(That‘s an F)

    徐焱
  • 支付宝支付-常用支付API详解(查询、退款、提现等)

    Maven项目引用JAR包可以参考 支付宝Wap支付你了解多少? 里面有详细的介绍

    Javen
  • 打卡GTD践行第二周

    给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

    程序员小王

扫码关注云+社区

领取腾讯云代金券