PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, December 21, 2022

[FIXED] How to copy a map in golang?

 December 21, 2022     dictionary, go, syntax     No comments   

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)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing