Python与Golang中给列表中字典按照某个key排序以及Go中给切片中的结构体排序

Golang中使用sort包按照结构体多个字段排序的正确方法!!!

type Bird struct {
    A1 int `json:"a1"`
    A2 int `json:"a2"`
    A3 int `json:"a3"`
    A4 int `json:"a4"`
}

func TestBirdSort(t *testing.T) {

    b1 := Bird{A1: 1, A2: 10, A3: 20, A4: 30}
    b2 := Bird{A1: 2, A2: 10, A3: 20, A4: 30}
    b3 := Bird{A1: 2, A2: 15, A3: 20, A4: 30}
    b4 := Bird{A1: 3, A2: 10, A3: 20, A4: 30}
    b5 := Bird{A1: 3, A2: 12, A3: 20, A4: 30}
    b6 := Bird{A1: 3, A2: 12, A3: 22, A4: 30}
    
    // Notice 注意切片中的元素最好是 指针!!!
    birds := []*Bird{&b2, &b4, &b5, &b6, &b1, &b3}

    // Notice 根据结构体切片中多个字段排序!!!!!注意判断逻辑不要有等于~
    sort.SliceStable(birds, func(i, j int) bool {

        // 先根据 a1 降序排序
        if birds[i].A1 > birds[j].A1 {
            return true
        }
        if birds[i].A1 < birds[j].A1 {
            return false
        }

        // 再根据 a2 降序排序
        if birds[i].A2 > birds[j].A2 {
            return true
        }
        if birds[i].A2 < birds[j].A2 {
            return false
        }

        // 最后根据 a3 降序排序
        if birds[i].A3 > birds[j].A3 {
            return true
        }
        if birds[i].A3 < birds[j].A3 {
            return false
        }

        return true
    })

    fmt.Println("ret1:>>>> ", gconv.String(birds))
    dump.P(birds)

    /*
        []*scripts_stroage.Bird [ #len=6
          &  scripts_stroage.Bird {
            A1: int(3),
            A2: int(12),
            A3: int(22),
            A4: int(30),
          },
          &  scripts_stroage.Bird {
            A1: int(3),
            A2: int(12),
            A3: int(20),
            A4: int(30),
          },
          &  scripts_stroage.Bird {
            A1: int(3),
            A2: int(10),
            A3: int(20),
            A4: int(30),
          },
          &  scripts_stroage.Bird {
            A1: int(2),
            A2: int(15),
            A3: int(20),
            A4: int(30),
          },
          &  scripts_stroage.Bird {
            A1: int(2),
            A2: int(10),
            A3: int(20),
            A4: int(30),
          },
          &  scripts_stroage.Bird {
            A1: int(1),
            A2: int(10),
            A3: int(20),
            A4: int(30),
          },
        ],
    */

}

参考文章

golang sort包 排序 ***

Golang sort包排序算法阅读分析 ***

前言

  最近写业务学到了在Golang中给slice中的map按照key排序的方法,想到Python中也有相关的需求与写法,总结一下方便以后使用。

Golang中的实现

  在Go中有一个内置的sort模块可以实现:

package test1

import (
    "fmt"
    "sort"
    "testing"
)

/*
数据的格式如下:
s=[
    {"no":21,"score":90},
    {"no":21,"score":80},
    {"no":25,"score":100},
    {"no":20,"score":66},
]
*/

func TestSortSliceMap(t *testing.T) {
    m1 := map[string]int{"no": 21, "score": 90}
    m2 := map[string]int{"no": 21, "score": 80}
    m3 := map[string]int{"no": 25, "score": 100}
    m4 := map[string]int{"no": 20, "score": 66}

    s1 := []map[string]int{m1, m2, m3, m4}

    // 排序后
    fmt.Println("排序前s1: ", s1)

    // 先根据no排序,no一样的话再根据score排序 ———— 从小到大排序
    sort.Slice(s1, func(i, j int) bool {
        if s1[i]["no"] == s1[j]["no"] {
            return s1[i]["score"] < s1[j]["score"]
        }
        return s1[i]["no"] < s1[j]["no"]
    })

    // 排序后
    fmt.Println("排序后s1: ", s1)

    /*
           结果:
           排序前s1:  [map[no:21 score:90] map[no:21 score:80] map[no:25 score:100] map[no:20 score:66]]
           排序后s1:  [map[no:20 score:66] map[no:21 score:80] map[no:21 score:90] map[no:25 score:100]]
    */
}

Python中的实现

简单的按照value排序

dic = {'a': 21, 'b': 5, 'c': 3, 'd': 54, 'e': 74, 'f': 0}

# 按照value的大小倒序排序
new_lst = sorted(dic.items(), key=lambda d: d[1], reverse=True)
print("new_lst: ", new_lst)
# new_lst:  [('e', 74), ('d', 54), ('a', 21), ('b', 5), ('c', 3), ('f', 0)]

# 重新构建字典
new_dic = {tu[0]: tu[1] for tu in new_lst}
print("new_dic: ", new_dic)
# new_dic:  {'e': 74, 'd': 54, 'a': 21, 'b': 5, 'c': 3, 'f': 0}

列表里面嵌套字典按照字典的多个key排序

import pprint

lst = [
    {"level": 19, "star":21, "time": 9},
    {"level": 29, "star":43, "time": 51},
    {"level": 22, "star":55, "time": 43},
    {"level": 22, "star":66, "time": 3},
    {"level": 17, "star":20, "time": 12},
    {"level": 17, "star":20, "time": 13},
]

"""
需求:
  level越大越靠前;
  level相同, star越大越靠前;
  level和star相同, time越小越靠前;
"""
print("lst0: ")
pprint.pprint(lst)

# 先按照time排序 默认是从小到大
lst.sort(key=lambda k:k["time"])
print("lst1: ")
pprint.pprint(lst)

# 再根据level跟star排序,从大到小
lst.sort(key=lambda k: (k["level"], k["star"]), reverse=True)
print("lst2: ")
pprint.pprint(lst)

"""
结果:
lst0: 
[{'level': 19, 'star': 21, 'time': 9},
 {'level': 29, 'star': 43, 'time': 51},
 {'level': 22, 'star': 55, 'time': 43},
 {'level': 22, 'star': 66, 'time': 3},
 {'level': 17, 'star': 20, 'time': 12},
 {'level': 17, 'star': 20, 'time': 13}]
lst1: 
[{'level': 22, 'star': 66, 'time': 3},
 {'level': 19, 'star': 21, 'time': 9},
 {'level': 17, 'star': 20, 'time': 12},
 {'level': 17, 'star': 20, 'time': 13},
 {'level': 22, 'star': 55, 'time': 43},
 {'level': 29, 'star': 43, 'time': 51}]
lst2: 
[{'level': 29, 'star': 43, 'time': 51},
 {'level': 22, 'star': 66, 'time': 3},
 {'level': 22, 'star': 55, 'time': 43},
 {'level': 19, 'star': 21, 'time': 9},
 {'level': 17, 'star': 20, 'time': 12},
 {'level': 17, 'star': 20, 'time': 13}]
""" 

Golang中给切片中的结构体排序 ***

Go中的排序函数如下:

1. Slice() 不稳定排序

2. SliceStable() 稳定排序

3. SliceIsSorted() 判断是否已排序

package sort_tests

import (
    "fmt"
    "sort"
    "testing"
)

type UserTask struct {
    Id   int
    Name string
    Type string
}

// slice里面是 结构体,根据结构体的某个字段去排序
func TestSortStructSlice(t *testing.T) {
    userTask1 := UserTask{Id: 1, Name: "task1", Type: "type1"}
    userTask2 := UserTask{Id: 2, Name: "task2", Type: "type2"}
    userTask3 := UserTask{Id: 3, Name: "task3", Type: "type3"}
    userTask4 := UserTask{Id: 4, Name: "task4", Type: "type4"}
    userTask5 := UserTask{Id: 5, Name: "task5", Type: "type5"}

    mySlice := []UserTask{userTask4, userTask3, userTask1, userTask5, userTask2}
    fmt.Println("=========排序前:==========", mySlice)
    // [{4 task4 type4} {3 task3 type3} {1 task1 type1} {5 task5 type5} {2 task2 type2}]

    // 1、从小到大排序 不稳定排序
    sort.Slice(mySlice, func(i, j int) bool {
        if mySlice[i].Id < mySlice[j].Id {
            return true
        }
        return false
    })
    fmt.Println("=========不稳定排序(从小到大)后:=========", mySlice)
    // [{1 task1 type1} {2 task2 type2} {3 task3 type3} {4 task4 type4} {5 task5 type5}]

    // 2、判断是否是 从小到大排序
    bLess := sort.SliceIsSorted(mySlice, func(i, j int) bool {
        if mySlice[i].Id < mySlice[i].Id {
            return true
        }
        return false
    })
    fmt.Println("======是否是从小到大排序: ", bLess) // true

    // 3、从大到小排序 稳定排序
    sort.SliceStable(mySlice, func(i, j int) bool {
        if mySlice[i].Id > mySlice[j].Id {
            return true
        }
        return false
    })
    fmt.Println("=========稳定排序(从大到小)后:=========", mySlice)
    // [{5 task5 type5} {4 task4 type4} {3 task3 type3} {2 task2 type2} {1 task1 type1}]

    // 4、判断是否是 从大到小排序
    bMore := sort.SliceIsSorted(mySlice, func(i, j int) bool {
        if mySlice[i].Id > mySlice[i].Id {
            return true
        }
        return false
    })
    fmt.Println("======是否是从小到大排序: ", bMore) // true
}

~~~

优先级特殊排序

 

 

posted on 2021-03-11 17:49  江湖乄夜雨  阅读(1103)  评论(0编辑  收藏  举报