首页 > 解决方案 > 如何在golang中按动态字段名对结构数组进行排序

问题描述

我想按动态字段对结构数组进行排序。这是结构

type user struct{
    Name string `json:"name"`
    Age int     `json:"age"`
    Status int  `json:"status "`
    Type  string  `json:"type"`
}

这是一个结构数组

var UserArray []user

我必须按给定字段对这个数组进行排序,该字段可以是用户结构的任何字段。但我会从 UI 接收该排序字段作为 JSON 标记。如下所示

sort := agnutil.GetQueryParamString(<json tag>, "sort", 0, "name")

我已经尝试过 golang 中的排序功能,但是如何动态使用它?

sort.Slice(UserArray , func(i, j int) bool {
        return UserArray[i].<givenfield>  < UserArray[j].<givenfield>
    })

标签: arrayssortinggo

解决方案


我想尝试按字段的 json 标记对结构片段进行排序,就是我最终得到的结果,以防它对任何人有所帮助:

package main

import (
    "fmt"
    "reflect"
    "sort"
)

func sortBy(jsonField string, arr []num) {
    if len(arr) < 1 {
        return
    }

    // first we find the field based on the json tag
    valueType := reflect.TypeOf(arr[0])

    var field reflect.StructField

    for i := 0; i < valueType.NumField(); i++ {
        field = valueType.Field(i)

        if field.Tag.Get("json") == jsonField {
            break
        }
    }

    // then we sort based on the type of the field
    sort.Slice(arr, func(i, j int) bool {
        v1 := reflect.ValueOf(arr[i]).FieldByName(field.Name)
        v2 := reflect.ValueOf(arr[j]).FieldByName(field.Name)

        switch field.Type.Name() {
        case "int":
            return int(v1.Int()) < int(v2.Int())
        case "string":
            return v1.String() < v2.String()
        case "bool":
            return !v1.Bool() // return small numbers first
        default:
            return false // return unmodified
        }
    })

    fmt.Printf("\nsort by %s:\n", jsonField)
    prettyPrint(arr)
}

func prettyPrint(arr []num) {
    for _, v := range arr {
        fmt.Printf("%+v\n", v)
    }
}

type num struct {
    Id   int    `json:"id"`
    Name string `json:"name"`
    Big  bool   `json:"big"`
}

func main() {

    userArray := []num{
        {1, "one", false},
        {5, "five", false},
        {40, "fourty", true},
        {9, "nine", false},
        {60, "sixty", true},
    }

    fmt.Println("original:")
    prettyPrint(userArray)

    sortBy("id", userArray[:])
    sortBy("name", userArray[:])
    sortBy("big", userArray[:])

}
original:
{Id:1   Name:one     Big:false}
{Id:5   Name:five    Big:false}
{Id:40  Name:fourty  Big:true}
{Id:9   Name:nine    Big:false}
{Id:60  Name:sixty   Big:true}

sort by id
{Id:1   Name:one     Big:false}
{Id:5   Name:five    Big:false}
{Id:9   Name:nine    Big:false}
{Id:40  Name:fourty  Big:true}
{Id:60  Name:sixty   Big:true}

sort by name
{Id:5   Name:five    Big:false}
{Id:40  Name:fourty  Big:true}
{Id:9   Name:nine    Big:false}
{Id:1   Name:one     Big:false}
{Id:60  Name:sixty   Big:true}

sort by big
{Id:1   Name:one     Big:false}
{Id:9   Name:nine    Big:false}
{Id:5   Name:five    Big:false}
{Id:40  Name:fourty  Big:true}
{Id:60  Name:sixty   Big:true}


推荐阅读