Sorting a Map of Structs – GOLANG

huangapple go评论71阅读模式
英文:

Sorting a Map of Structs - GOLANG

问题

我有一个结构体的映射表,通过将数据流传输到Go程序来填充。更新映射表的方式类似于下面的示例。

一旦我填充好这个结构体映射表,最好(或者说好的)的方法是按照结构体中count字段的值对这个映射表进行排序。

package main

type data struct {
    count int64
}

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

你可以在这里运行这个示例:http://play.golang.org/p/OawL6QIXuO

英文:

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

答案1

得分: 29

正如siritinga已经指出的,map的元素是无序的,所以你不能对其进行排序。

你可以创建一个slice,并使用sort包对元素进行排序:

package main

import (
	"fmt"
	"sort"
)

type dataSlice []*data

type data struct {
	count int64
	size  int64
}

// Len是sort.Interface的一部分。
func (d dataSlice) Len() int {
	return len(d)
}

// Swap是sort.Interface的一部分。
func (d dataSlice) Swap(i, j int) {
	d[i], d[j] = d[j], d[i]
}

// Less是sort.Interface的一部分。我们使用count作为排序的值。
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)
	}		
	
	// 我们只是在其中一个结构体上加了3
	d := m["x"]
	d.count += 3
	
	sort.Sort(s)
	
	for _, d := range s {
		fmt.Printf("%+v\n", *d)
	}
}

输出:

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

Playground

编辑

更新了示例,使用指针并包含一个map,这样你既可以进行查找,又可以有一个可以排序的slice。

英文:

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 (
	&quot;fmt&quot;
	&quot;sort&quot;
)

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 &lt; d[j].count
}

func main() {
	m := map[string]*data {
		&quot;x&quot;: {0, 0},
		&quot;y&quot;: {2, 9},
		&quot;z&quot;: {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[&quot;x&quot;]
	d.count += 3
	
	sort.Sort(s)
	
	for _, d := range s {
		fmt.Printf(&quot;%+v\n&quot;, *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.

huangapple
  • 本文由 发表于 2013年11月13日 14:35:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/19946992.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定