Issue
I can offer decomposition of map to 2 slices example:
func decomposeMap(m map[string]int) ([]string, []int) {
var i uint
l := len(m)
keys, values := make([]string, l), make([]int, l)
for keys[i], values[i] = range m {
i++
}
return keys, values
}
but I am failing to write map copying:
func copyMap(m map[string]int) map[string]int {
m2 := make(map[string]int, len(m))
for id, m2[id] = range m {} // error - id is not declared
for id, m2[id] := range m {} // error with m2[id] already declared
// id should not be accessible here, it should exist only inside loop
return m2
}
I can declare id as a var, but I dont want it to be available outside for loop. How can i mix assigment and declaration, eg: for id:=, m[id]= range m {}
?
So it will declare index just inside for loop, and will be not accessible outside?
Solution
The id
variable must be declared before for
, because you can't use short variable declaration with m2[id]
.
func copyMap(m map[string]int) map[string]int {
m2 := make(map[string]int, len(m))
var id string
for id, m2[id] = range m {
}
return m2
}
But! This won't duplicate the map! The key is only assigned to id
after m2[id]
is already evaluated, so this loop will assign values to keys of the previous iteration, this is not duplicating, this is "shuffling"!
This is basically a tuple assignment (key and value are assigned to id, m2[id]
). Spec: Assignments:
The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.
So first id
and m2[id]
are evaluated (including the index expression), so id
is not "yet" changed, so the value from the previous iteration is used, and only after this are the new key and values assigned.
To demonstrate, see:
m := map[string]int{
"one": 1,
"two": 2,
"three": 3,
}
m2 := copyMap(m)
fmt.Println(m2)
Output (try it on the Go Playground):
map[:1 one:2 two:3]
The values are assigned to different keys (different than in the source map), and one value is assigned to the empty string key in the first iteration (the default, zero value of id
).
To duplicate the map, simply use:
for id, v := range m {
m2[id] = v
}
Or if you want to avoid the temporary assignment:
for id := range m {
m2[id] = m[id]
}
Answered By - icza Answer Checked By - Candace Johnson (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.