这是古老的“为什么我的地图打印不正常”问题的变体。
我有(相当大)数量的形式的地图map[MyKey]MyValue
,其中MyKey
和MyValue
(通常)是结构。我对所有键类型都有“更少”的功能。
我需要按顺序遍历地图。(具体来说,该类型的 less 函数定义的顺序。)现在,我的代码如下所示:
type PairKeyValue struct {
MyKey
MyValue
}
type PairKeyValueSlice []Pair
func (ps PairKeyValueSlice) Len() int {
return len(ps)
}
func (ps PairKeyValueSlice) Swap(i,j int) {
ps[i], ps[j] = ps[j], ps[i]
}
func (ps PairKeyValueSlice) Less(i,j int) {
return LessKey(ps[i].MyKey, ps[j].MyKey)
}
func NewPairKeyValueSlice(m map[MyKey]MyValue) (ps PairKeyValueSlice) {
ps = make(PairKeyValueSlice, len(m))
i := 0
for k,v := range m {
ps[i] = PairKeyValue{k,v}
i++
}
sort.Sort(ps)
}
然后,任何时候我想要一个有序迭代,它看起来像:
var m map[MyKey]MyValue
m = GetMapFromSomewhereUseful()
for _, kv := range NewPairKeyValueSlice(m) {
key := kv.MyKey
value := kv.MyValue
DoUsefulWork(key, value)
}
这似乎在很大程度上奏效了。问题是它非常冗长。特别是因为手头的问题实际上与实现有序映射几乎没有关系,而实际上与循环中的有用工作有关。
此外,我有几种不同的键和值类型。因此,每次我想按顺序遍历地图时,我都会复制/粘贴所有代码,并MyKey
使用新键和MyValue
新值进行查找/替换。复制/粘贴到那个量级是……“臭”。这已经成为一件麻烦事,因为我已经犯了一些必须多次修复的错误。
这种技术也有缺点,它需要制作所有键和值的完整副本。这是不可取的,但我看不到解决方法。(我可以将其简化为键,但它不会改变问题的主要性质。)
这个问题正在尝试用字符串做同样的事情。这个问题用字符串和整数来做。这个问题意味着您需要使用反射,并且必须有一个 switch 语句来打开所有可能的类型,包括所有用户定义的类型。
但是对于那些对地图没有确定性迭代感到困惑的人,似乎必须有一个更好的解决方案来解决这个问题。我来自 OO 背景,所以我可能缺少一些基本的东西。
那么,有没有一种合理的方法可以按顺序迭代地图?
更新:编辑问题以获取有关来源的更多信息,以防有比这更好的解决方案。
我有很多东西需要分组输出。每个分组级别的结构如下所示:
type ObjTypeTree struct {
Children map[Type]*ObjKindTree
TotalCount uint
}
type ObjKindTree struct {
Children map[Kind]*ObjAreaTree
TotalCount uint
}
type ObjAreaTree struct {
Children map[Area]*ObjAreaTree
TotalCount uint
Objs []*Obj
}
然后,我将遍历 中的子项ObjTypeTree
以打印类型分组。对于其中的每一个,我都会遍历ObjKindTree
以打印 Kind 分组。迭代是通过类型上的方法完成的,每种类型都需要稍微不同的方式来打印其分组级别。需要按顺序打印组,这会导致问题。