# 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笔记：类型检验

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

• ### golang学习之接口型函数

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

• ### Flutter布局篇（1）--水平和垂直布局详解

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

• ### 分治策略之最大子数组（Python实现）

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

• ### startUML怎么画interface接口 原

图1

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

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

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

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

• ### 打卡GTD践行第二周

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