在遍历原始映射时,重命名映射键的惯用方式是什么?

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

Idiomatic way of renaming keys in map while ranging over the original map

问题

我正在尝试使用另一个映射r的键和值来重命名映射o的键。

下面的尝试似乎失败了,我猜测原因与我在遍历映射的同时修改它有关 - 我得到了一个额外的blank键。

我可以简单地将映射复制到一个新的目标映射中,但是该映射是一个更复杂的结构的一部分 - 因此任何尝试都需要我对该结构进行递归深拷贝,而我宁愿避免这样做。

o := make(map[string]string) // 原始映射
r := make(map[string]string) // 替换映射 原始键 -> 目标键

o["a"] = "x"
o["b"] = "y"

r["a"] = "1"
r["b"] = "2"

fmt.Println(o) // -> map[a:x b:y]

for k, v := range o {
    o[r[k]] = v
}

delete(o, "a")
delete(o, "b")

fmt.Println(o) // -> map[1:x 2:y :y]

我期望这将打印map[1:x 2:y]

英文:

I'm attempting to rename the keys of a map o using the keys and values of another map r.

This below attempt seems to fail for reasons I guess are related to the fact that I'm modifying the map while also ranging over it — I get an extra blank key.

I could simply copy the map over to a new destination map, however the map is part of a much more complex struct — so any attempts will require me to do some kind of recursive deep copy of that struct, which I would rather avoid.

o := make(map[string]string) // original map
r := make(map[string]string) // replacement map original -> destination keys

o["a"] = "x"
o["b"] = "y"

r["a"] = "1"
r["b"] = "2"

fmt.Println(o) // -> map[a:x b:y]

for k, v := range o {
    o[r[k]] = v
}

delete(o, "a")
delete(o, "b")

fmt.Println(o) // -> map[1:x 2:y :y]

I am expecting this to print map[1:x 2:y].

答案1

得分: 4

如果你同时遍历和修改目标映射,它会产生一个意外的行为,即空键和值。我以前见过这种情况(有时发生,但不总是)。我还没有对此进行过研究(也许其他 Stack Overflow 的成员可以在这里提供一些帮助)。

如果你遍历源映射并更新目标映射,你会得到期望的行为。

for k, v := range r {
    o[v] = o[k]
    delete(o, k)
}

输出:

Modified map: map[1:x 2:y]

Play 链接:https://play.golang.org/p/heVbZFe0Nu

英文:

If you range over and modify targeted map at same time, it gives an unexpected behavior which empty key with value. I have seen that before (it happens some time not always). I have not researched around it (may be fellow SO members can shed some light here).

If you do range over source map and update targeted map, you get a desired behavior.

for k, v := range r {
	o[v] = o[k]
    delete(o, k)
}

Output:

Modified map: map[1:x 2:y]

Play link: https://play.golang.org/p/heVbZFe0Nu

答案2

得分: 2

只需对另一个映射进行迭代:

o := make(map[string]string) // 原始映射
r := make(map[string]string) // 替换映射 原始键 -> 目标键

o["a"] = "x"
o["b"] = "y"

r["a"] = "1"
r["b"] = "2"

fmt.Println(o) // -> map[a:x b:y]

for k, v := range r {
    o[v] = o[k]
    delete(o, k)
}
fmt.Println(o) // -> map[1:x 2:y]
英文:

Simply iterate over the other map:

o := make(map[string]string) // original map
r := make(map[string]string) // replacement map original -> destination keys

o["a"] = "x"
o["b"] = "y"

r["a"] = "1"
r["b"] = "2"

fmt.Println(o) // -> map[a:x b:y]

for k, v := range r {
    o[v] = o[k]
    delete(o, k)
}
fmt.Println(o) // -> map[1:x 2:y]

答案3

得分: 0

PEBKAC一如既往,这个方法似乎通过首先检查替换映射中是否存在替换键,并一举删除它来很好地解决了问题。

for k, v := range o {
    if _, ok := r[k]; ok {
        o[r[k]] = v
        delete(o, k)
    }
}
英文:

PEBKAC as always, this seems to solve it quite nicely by first checking if the replacement key is present in the replacement map and also deletes it in one fell swoop

for k, v := range o {
	if _, ok := r[k]; ok {
		o[r[k]] = v
		delete(o, k)
	}
}

huangapple
  • 本文由 发表于 2017年7月17日 03:31:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/45132563.html
匿名

发表评论

匿名网友

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

确定