Golang Sort为映射

时间:2015-11-12 19:52:55

标签: sorting go

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}]

我对3个功能做错了吗?

2 个答案:

答案 0 :(得分:4)

您将不存在的索引传递给Swap(i, j)

地图类型是复合的。它根据其他两种类型定义:键类型和值类型。例如:

map[string]bool

在上一个示例中,string是键类型,bool是值类型。

如您所知,地图访问返回1或2个值。在像您这样的1返回值上下文中,当给定不存在的索引时,映射访问将返回映射的值类型的零值。

这意味着,如果您在m["im_not_defined"]类型的某个地图m上访问map[string]bool,则会获得bool if a, k := t[uint32(i)]; k { t[uint32(j)] = a } else { panic("undefined index") } 的返回值(地图的值类型)。

您可以检查是否通过执行定义索引(在Swap内部):

j

类似于i

所以基本上,如果GeoNameTally未定义,则t[j]的零值会分配给from pyparsing import * from datetime import datetime # for the most part, we suppress punctuation - it's important at parse time # but just gets in the way afterwards LBRACE,RBRACE,COLON,DBLQ,LBRACK,RBRACK = map(Suppress, '{}:"[]') DBLQ2 = DBLQ + DBLQ # define some scalar value expressions, including parse-time conversion parse actions realnum = Regex(r'[+-]?\d+\.\d*').setParseAction(lambda t:float(t[0])) integer = Regex(r'[+-]?\d+').setParseAction(lambda t:int(t[0])) timestamp = Regex(r'""\d{4}-\d{2}-\d{2}T\d{2}:\d{2}""') timestamp.setParseAction(lambda t: datetime.strptime(t[0][2:-2],'%Y-%m-%dT%H:%M')) string_value = QuotedString('""') # define our base key ':' value expression; use a Forward() placeholder # for now for value, since these things can be recursive key = Optional(DBLQ2) + Word(alphas, alphanums+'_') + DBLQ2 value = Forward() key_value = Group(key + COLON + value) # objects can be values too - use the Dict class to capture keys as field names obj = Group(Dict(LBRACE + OneOrMore(key_value) + RBRACE)) objlist = (LBRACK + ZeroOrMore(obj) + RBRACK) # define expression for previously-declared value, using <<= operator value <<= timestamp | string_value | realnum | integer | obj | Group(objlist) # the outermost objects are enclosed in "s, and list of them can be given with '|' delims quotedObj = DBLQ + obj + DBLQ obsList = delimitedList(quotedObj, delim='|') ,这会导致您的“空”(零)值。

无论如何,如果你想排序任何东西,你将不得不使用切片。根据定义,地图是无序的。

答案 1 :(得分: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)
}