Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting a Map of Structs - GOLANG

I have a map of structs that I am populating by streaming data to a Go program. The way the map is updated is similar to the example below.

Once I have this map of structs populated, what is the best (or good) way to sort this map by the values of the count field in the struct?

package main

type data struct {
    count int64
}

func main() {
    m := make(map[string]data)
    m["x"] = data{0, 0}
    if xx, ok := m["x"]; ok {
        xx.count = 2
        m["x"] = xx
    } else {
        panic("X isn't in the map")
    }
}

This example can be run here: http://play.golang.org/p/OawL6QIXuO

like image 617
DJElbow Avatar asked Nov 13 '13 06:11

DJElbow


1 Answers

As siritinga already pointed out, the elements of a map isn't ordered, so you cannot sort it.

What you can do is to create a slice and sort the elements using the sort package:

package main

import (
    "fmt"
    "sort"
)

type dataSlice []*data

type data struct {
    count int64
    size  int64
}

// Len is part of sort.Interface.
func (d dataSlice) Len() int {
    return len(d)
}

// Swap is part of sort.Interface.
func (d dataSlice) Swap(i, j int) {
    d[i], d[j] = d[j], d[i]
}

// Less is part of sort.Interface. We use count as the value to sort by
func (d dataSlice) Less(i, j int) bool {
    return d[i].count < d[j].count
}

func main() {
    m := map[string]*data {
        "x": {0, 0},
        "y": {2, 9},
        "z": {1, 7},
    }

    s := make(dataSlice, 0, len(m))

    for _, d := range m {
        s = append(s, d)
    }       

    // We just add 3 to one of our structs
    d := m["x"]
    d.count += 3

    sort.Sort(s)

    for _, d := range s {
        fmt.Printf("%+v\n", *d)
    }
}

Output:

{count:1 size:7}
{count:2 size:9}
{count:3 size:0}

Playground

Edit

Updated the example to use pointers and to include a map so that you can both do lookups and have a slice to sort over.

like image 124
ANisus Avatar answered Oct 12 '22 12:10

ANisus