英文:
Golang Sort adds extra values to 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}]
我在这三个函数中做错了什么吗?
英文:
type GeoNameTally struct {
Id uint32
Count uint32
}
type Tally map[uint32]GeoNameTally
Above are the structs i have. The idea is pretty simple. I'm just tallying how many times something occurs.
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)] }
Everything works perfectly fine until I get to the sort. Right before sort, the map looks fine:
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}]
However right after sort.Sort(myTally)
the map has extra and empty values as you can see from the following output:
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}]
Have I done something wrong to the 3 functions?
答案1
得分: 4
你正在向Swap(i, j)
传递不存在的索引。
映射类型是复合类型。它由两个其他类型定义:键类型和值类型。例如:
map[string]bool
在上面的示例中,string
是键类型,bool
是值类型。
正如你可能知道的,映射访问返回1个或2个值。在像你这样的1个返回值的上下文中,当给定一个不存在的索引时,映射访问将返回映射值类型的零值。
这意味着如果你在类型为map[string]bool
的某个映射m
上访问m["im_not_defined"]
,你将得到一个返回值,它是bool
(映射值类型)的零值。
你可以通过以下方式检查索引是否定义(在Swap
内部):
if a, k := t[uint32(i)]; k {
t[uint32(j)] = a
} else {
panic("undefined index")
}
对于j
也是类似的。
所以基本上,如果i
未定义,GeoNameTally
的零值将赋给t[j]
,这导致你的“空”(零)值。
无论如何,如果你想要对任何东西进行_排序_,你将需要使用切片。映射在定义上是无序的。
英文:
You're passing inexistent indexes to Swap(i, j)
.
A map type is composite. It is defined in terms of 2 other types: the key type and the value type. Example:
map[string]bool
In the previous example, string
is the key type, bool
is the value type.
As you may know, map access returns 1 or 2 values. In a 1 return value context like yours, a map access will return the zero-value for the map's value type when given an inexistent index.
This means that if you access m["im_not_defined"]
on some map m
of type map[string]bool
, you'll get a return value that is the zero-value for bool
(the map's value type).
You can check if the indexes are defined by doing (inside Swap):
if a, k := t[uint32(i)]; k {
t[uint32(j)] = a
} else {
panic("undefined index")
}
And analogously for j
.
So basically, if i
is undefined, the zero-value of GeoNameTally
is assigned to t[j]
and that causes your "empty" (zero) values.
Anyhow, if you want to sort anything, you'll have to use a slice. A map is unordered by definition.
答案2
得分: 0
从Go 1.8开始,有一种更简单的方法可以对切片进行排序,而无需定义新类型。你只需创建一个Less(匿名)lambda函数。
a := []int{5, 3, 4, 7, 8, 9}
sort.Slice(a, func(i, j int) bool {
return a[i] < a[j]
})
for _, v := range a {
fmt.Println(v)
}
英文:
As of Go 1.8, there is an easier way to sort a slice that does not require you to define new types. You simply create a Less (anonymous) lambda.
a := []int{5, 3, 4, 7, 8, 9}
sort.Slice(a, func(i, j int) bool {
return a[i] < a[j]
})
for _, v := range a {
fmt.Println(v)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论