猿问

Golang Sort 为 map 添加额外的值

type GeoNameTally struct {

    Id    uint32

    Count uint32

}


type Tally map[uint32]GeoNameTally

以上是我拥有的结构。这个想法很简单。我只是在计算某事发生了多少次。


func (t Tally) Len() int           { return len(t) }

func (t Tally) Less(i, j int) bool { return t[uint32(i)].Count < t[uint32(j)].Count }

func (t Tally) Swap(i, j int)      { t[uint32(i)], t[uint32(j)] = t[uint32(j)], t[uint32(i)] }

一切正常,直到我开始排序。在排序之前,地图看起来不错:


map[1043487:{Id:1043487 Count:1} 1043503:{Id:1043503 Count:1} 1043444:{Id:1043444 Count:1} 1043491:{Id:1043491 Count:1} 1043459:{Id:1043459 Count:1} 1043475:{Id:1043475 Count:1} 1043464:{Id:1043464 Count:1} 1043441:{Id:1043441 Count:1} 1043470:{Id:1043470 Count:1} 1043460:{Id:1043460 Count:1}]

但是,sort.Sort(myTally)在地图具有额外值和空值之后,您可以从以下输出中看到:


map[1043503:{Id:1043503 Count:1} 1043491:{Id:1043491 Count:1} 1043459:{Id:1043459 Count:1} 1043475:{Id:1043475 Count:1} 4:{Id:0 Count:0} 8:{Id:0 Count:0} 1043487:{Id:1043487 Count:1} 1:{Id:0 Count:0} 5:{Id:0 Count:0} 9:{Id:0 Count:0} 1043470:{Id:1043470 Count:1} 2:{Id:0 Count:0} 6:{Id:0 Count:0} 1043444:{Id:1043444 Count:1} 1043441:{Id:1043441 Count:1} 1043460:{Id:1043460 Count:1} 3:{Id:0 Count:0} 7:{Id:0 Count:0} 1043464:{Id:1043464 Count:1}]

我对这三个功能做错了吗?


ITMISS
浏览 141回答 2
2回答

波斯汪

您将不存在的索引传递给Swap(i, j).地图类型是复合的。它是根据另外两种类型定义的:键类型和值类型。例子:map[string]bool在前面的例子中,string是键类型,bool是值类型。您可能知道,地图访问返回 1 或 2 个值。在像您这样的 1 返回值上下文中,当给定不存在的索引时,地图访问将返回地图值类型的零值。这意味着如果您访问m["im_not_defined"]某个mtype 的地图map[string]bool,您将获得一个返回值,该值是bool(地图的值类型)的零值。您可以通过执行(在 Swap 中)来检查索引是否定义:if a, k := t[uint32(i)]; k {&nbsp; &nbsp; t[uint32(j)] = a} else {&nbsp; &nbsp; panic("undefined index")}类似地对于j.所以基本上,如果i未定义,则将 的零值GeoNameTally分配给t[j]并导致您的“空”(零)值。无论如何,如果你想对任何东西进行排序,你就必须使用切片。根据定义,地图是无序的。

慕后森

从 Go 1.8 开始,有一种更简单的方法可以对切片进行排序,而无需您定义新类型。您只需创建一个 Less(匿名)lambda。a := []int{5, 3, 4, 7, 8, 9}sort.Slice(a, func(i, j int) bool {&nbsp; &nbsp; return a[i] < a[j]})for _, v := range a {&nbsp; &nbsp; fmt.Println(v)}
随时随地看视频慕课网APP

相关分类

Go
我要回答