jonathanGB
jonathanGB

Reputation: 1540

Go: append directly to slice found in a map

I wanted to create a map of slices where values are appended to the corresponding slice. However, when trying to append directly to the slice returned by accessing it (see comment below), it would not be stored, so I had to go with the long form access (line below the comment).

Why is it so? I expected the access to the map to return some sort of pointer, so in my mind mappedAminoAcid == aminoAcidsToCodons[aminoAcid]; clearly, I'm wrong.

Thanks!

aminoAcidsToCodons := map[rune][]string{}
for codon, aminoAcid := range utils.CodonsToAminoAcid {
    mappedAminoAcid, ok := aminoAcidsToCodons[aminoAcid]

    if ok {
        // NOT WORKING: mappedAminoAcid = append(mappedAminoAcid, codon)
        aminoAcidsToCodons[aminoAcid] = append(mappedAminoAcid, codon)
    } else {
        aminoAcidsToCodons[aminoAcid] = []string{codon}
    }
}

Upvotes: 17

Views: 21839

Answers (2)

Jack
Jack

Reputation: 1076

If you're in control of the underlying data structure, you can make this way easier on yourself by using a pointer to the slice:

// https://go.dev/play/p/s0vBe6-Z6rY

mymap := map[rune]*[]string{}

mymap['x'] = &[]string{"hello"}
*mymap['x'] = append(*mymap['x'], "world")

fmt.Printf("%v\n", mymap['x'])

// mymap.x -> ["hello", "world"]

This also allows you to reference the list in another variable:

// https://go.dev/play/p/j2QR0J3YQPW

mymap := map[rune]*[]string{}
mymap['x'] = &[]string{"hello"}

ref := mymap['x']
*ref = append(*ref, "world")

fmt.Printf("%v\n", mymap['x'])

// mymap.x -> ["hello", "world"]

Upvotes: -1

Peter
Peter

Reputation: 31691

append returns a new slice if the underlying array has to grow to accomodate the new element. So yes, you have to put the new slice back into the map. This is no different from how strings work, for instance:

var x map[string]string
x["a"] = "foo"

y := x["a"]
y = "bar"

// x["a"] is still "foo"

Since a nil slice is a perfectly fine first argument for append, you can simplify your code to:

aminoAcidsToCodons := map[rune][]string{}
for codon, aminoAcid := range utils.CodonsToAminoAcid {
    aminoAcidsToCodons[aminoAcid] = append(aminoAcidsToCodons[aminoAcid], codon)
}

Upvotes: 15

Related Questions