简体   繁体   中英

How to multiple sort a map[string]interface{} type in go lang?

Scenario : Consider I have a JSON data to be processed in go lang Now I am using map[string]interface{} type using package encoding/json by doing marshal/unmarshal

Below is the JSON data:

{
    "MysoreCity": {
        "Population": 1000,
        "VehicleCount": 1700,
        "Temperature": 33
    },
    "BangaloreCity": {
        "Population": 1000,
        "VehicleCount": 3500,
        "Temperature": 33
    },
    "KolarCity": {
        "Population": 1250,
        "VehicleCount": 3500,
        "Temperature": 31
    },
    "TumkurCity": {
        "Population": 800,
        "VehicleCount": 300,
        "Temperature": 29
    }
}

Now I want to perform a multi-sort descending order on the basis of priority, say priority is Temperature , Population , VehicleCount then I want the output to be like

{
    "BangaloreCity": {
        "Population": 1000,
        "VehicleCount": 3500,
        "Temperature": 33
    },
    "MysoreCity": {
        "Population": 1000,
        "VehicleCount": 1700,
        "Temperature": 33
    },
    "KolarCity": {
        "Population": 1250,
        "VehicleCount": 3500,
        "Temperature": 31
    },
    "TumkurCity": {
        "Population": 800,
        "VehicleCount": 300,
        "Temperature": 29
    }
}

So the sorting with respect to some dynamic set of priorities.

Issue: I am not getting any clues how to sort it in go lang. I am new to go lang and found something while searching for sorting my data; where it is mentioned as below (source: link )

When iterating over a map with a range loop, the iteration order is not specified and is not guaranteed to be the same from one iteration to the next.

Question: Could anyone put some light on how to do this kind of sorting with similar JSON data?

This answer is more about the methodology for solving this problem than a specific solution. I think it's more what you need at this point because you're not close to an actual solution. Here are the simple procedural steps;

1) define a type for this, I'll call it City from here on;

"TumkurCity": {
    "Population": 800,
    "VehicleCount": 300,
    "Temperature": 29
}

type City struct {
    Population   int
    VehicleCount int
    Temperature  int
    Name         string
}

2) unmarshal into a map[string]City

3) use a method like this to transform the data;

func ToSlice(m map[string]City) []City {
    cities := make([]City, 0, len(m))
    for k, v := range m {
        v.Name = k
        cities = append(cities, v)
    }
    return cities
}

4) define some method to sort the cities however it is you want

I wrote that code in the browser so it hasn't been tested or anything. It should provide a sufficient example of how to handle it. When you unmarshal your City types will have no value for name so you can just assign the key (the cities name) to that later on. put them in a slice or array, sort that. Pretty simple if you follow those steps.

I did this function get a result map from N maps and its sorted keys.

func getSortedKeys(maps ...map[string]string) (map[string]string, []string) {
    var keys []string
    resultMap := map[string]string{}

    for _, currMap := range maps {
        for k, v := range currMap {
            resultMap[k] = v
            keys = append(keys, k)
        }
    }
    sort.Strings(keys)
    return resultMap, keys

}

Outside the function you can do:

  concatenedMaps, keys := getSortedKeys(map1,map2)
  for _, k := range keys {
        value := concatenedMaps[k]
  }

you can use https://github.com/rxwycdh/rxhash rxhash.SortMap , can sort nested complex map by key.

for example:

import "github.com/rxwycdh/rxhash"

dd := map[string]any{
    "MysoreCity": map[string]any{
        "Population":   1000,
        "VehicleCount": 1700,
        "Temperature":  33,
    },
    "BangaloreCity": map[string]any{
        "Population":   1000,
        "VehicleCount": 3500,
        "Temperature":  33,
    },
    "KolarCity": map[string]any{
        "Population":   1250,
        "VehicleCount": 3500,
        "Temperature":  31,
    },
    "TumkurCity": map[string]any{
        "Population":   800,
        "VehicleCount": 300,
        "Temperature":  29,
    },
}

b, _ := json.Marshal(rxhash.SortMap(dd))
println(string(b))

output:

{
    "BangaloreCity": {
        "Population": 1000,
        "Temperature": 33,
        "VehicleCount": 3500
    },
    "KolarCity": {
        "Population": 1250,
        "Temperature": 31,
        "VehicleCount": 3500
    },
    "MysoreCity": {
        "Population": 1000,
        "Temperature": 33,
        "VehicleCount": 1700
    },
    "TumkurCity": {
        "Population": 800,
        "Temperature": 29,
        "VehicleCount": 300
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM