go

Golang 实现结构体数组按多字段排序

依然范儿特西
2021-11-24 / 0 评论 / 11 阅读 / 正在检测是否收录...

php 排序写法

近期因项目重构(php->golang),涉及到一些将对象列表中的对象按不同的字段(属性)排序;

在 php 中,可以使用 usort + 自定义的排序函数轻松实现;

PHP usort 官方文档

下面我们先看一个在 php 中的例子:

下面是一个待排序待数组

<?php

    $result = array(
        array(
            "val" => "f",
            "mtime" =>  1595144638,
            "orderval"=>4
        ),
        array(
            "val" => "d",
            "mtime" =>  1595144646,
            "orderval"=>2
        ),
        array(
            "val" => "a",
            "mtime" =>  1595144648,
            "orderval"=>8
        ),
        array(
            "val" => "t",
            "mtime" =>  1595144648,
            "orderval"=>5
        ),
        array(
            "val" => "e",
            "mtime" =>  1595144650,
            "orderval"=>3
        )
    );

我们目前待目标是将该数组中待对象

按 mtime 从大到小排序;如果 mtime 字段

的值相等,则按 orderval 从大到小排,最终想要的结果为:

e,a,t,d,f

[
    {"val"=>"e","mtime"=>1595144650,"orderval"=>3},
    {"val"=>"a","mtime"=>1595144648,"orderval"=>8},
    {"val"=>"t","mtime"=>1595144648,"orderval"=>5},
    {"val"=>"d","mtime"=>1595144646,"orderval"=>2},
    {"val"=>"f","mtime"=>1595144638,"orderval"=>4}
]

我们首先定义一个自定义函数,然后巧妙使用 usort 函数去调用的自定义函数,最终实现目标,直接上代码:

php
   $result = array(
        array(
            "val" => "f",
            "mtime" =>  1595144638,
            "orderval"=>4
        ),
        array(
            "val" => "d",
            "mtime" =>  1595144646,
            "orderval"=>2
        ),
        array(
            "val" => "a",
            "mtime" =>  1595144648,
            "orderval"=>8
        ),
        array(
            "val" => "t",
            "mtime" =>  1595144648,
            "orderval"=>5
        ),
        array(
            "val" => "e",
            "mtime" =>  1595144650,
            "orderval"=>3
        )
    );

    //按mtime 从大到小;如果mtime 相等,则按orderval 从大到小;
    usort($result, function ($v1, $v2) {
        if ($v1['mtime'] < $v2['mtime'] || ($v1['mtime'] == $v2['mtime'] && $v1['orderval'] < $v2['orderval'])) {
            return 1;
        } else {
            return -1;
        }
    });
    var_dump($result);

运行结果:

array(5) {
  [0]=>
  array(3) {
    ["val"]=>
    string(1) "e"
    ["mtime"]=>
    int(1595144650)
    ["orderval"]=>
    int(3)
  }

  [1]=>
  array(3) {
    ["val"]=>
    string(1) "a"
    ["mtime"]=>
    int(1595144648)
    ["orderval"]=>
    int(8)

  }

  [2]=>
  array(3) {
    ["val"]=>
    string(1) "t"
    ["mtime"]=>
    int(1595144648)
    ["orderval"]=>
    int(5)
  }

  [3]=>
  array(3) {
    ["val"]=>
    string(1) "d"
    ["mtime"]=>
    int(1595144646)
    ["orderval"]=>
    int(2)
  }

  [4]=>
  array(3) {
    ["val"]=>
    string(1) "f"
    ["mtime"]=>
    int(1595144638)
    ["orderval"]=>
    int(4)
  }

}

那么同样的功能,如果要用 golang 来实现,应如何办呢?

golang 排序

下面我们首先讲讲 golang 官方对排序 对支持,然后给出具体对例子;

package main

import (
    "fmt"
    "sort"
)

type Obj struct {
    Var      string `json:"var"`
    Mtime    int    `json:"mtime"`
    Orderval int    `json:"orderval"`

}

type List []Obj

func (p List) Len() int {
    return len(p)
}

// 此处排序是从大到小的, 如果想升序,可以把此方法里的 判定 改为 相反的判定即可
func (p List) Less(i, j int) bool {
    if p[i].Mtime > p[j].Mtime {
        return true
    }
    if p[i].Mtime < p[j].Mtime {
        return false
    }
    return p[i].Orderval > p[j].Orderval
}

func (p List) Swap(i, j int) {
    p[i], p[j] = p[j], p[i]
}

func (p *List) Sort() {
    sort.Sort(p)
}

func main() {
    s := List{{"f", 1595144638, 4}, {"d", 1595144646, 2}, {"a", 1595144648, 8}, {"t", 1595144648, 5}, {"e", 1595144650, 3}}
    fmt.Println(s)
    s.Sort()
    fmt.Println(s)

}

// 如果想使用传入的方法来写,可以把main 方法 的写法改为下边这个
//func toSortAsc(UserList []Obj)[]Obj{
//    s := List{}
//    for _,v := range UserList{
//        s = append(s,v)
//    }
//    s.Sort()
//    return s
//}

再举一个简单的例子

package main

import (
    "fmt"
    "sort"
)

type Instance struct {
    Domain     string   `json:"domain"`
    Ip         string   `json:"ip"`
    Containers []string `json:"containers,omitempty"`
}

func main() {
    instances := make([]*Instance, 0, 10)

    i1 := &Instance{}
    i1.Domain = "zhap"
    i1.Ip = "1"
    instances = append(instances, i1)

    i2 := &Instance{}
    i2.Domain = "abc"
    i2.Ip = "2"
    instances = append(instances, i2)

    i3 := &Instance{}
    i3.Domain = "mid"
    i3.Ip = "3"
    instances = append(instances, i3)

    fmt.Println("排序前 ")
    for _, v := range instances {
        fmt.Println(*v)
    }
    sort.Slice(instances, func(i, j int) bool {
        return instances[i].Domain < instances[j].Domain
    })
    fmt.Println("排序后 ")
    for _, v := range instances {
        fmt.Println(*v)
    }
}
0

评论 (0)

取消