go 自定义排序

2019-11-22 00:06:33 浏览数 (1)

自己来排一排 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)
}

0 人点赞