简体   繁体   English

如何在 Go 中更新地图值

[英]How to update map values in Go

I want to build a map with string key and struct value with which I'm able to update struct value in the map identified by map key.我想用字符串键和结构值构建一个映射,我可以用它来更新映射键标识的映射中的结构值。

I've tried this and this which doesn't give me desired output.我试过这个这个并没有给我想要的输出。

What I really want is this:我真正想要的是:

Received ID: D1 Value: V1
Received ID: D2 Value: V2
Received ID: D3 Value: V3
Received ID: D4 Value: V4
Received ID: D5 Value: V5

Data key: D1 Value: UpdatedData for D1
Data key: D2 Value: UpdatedData for D2
Data key: D3 Value: UpdatedData for D3
Data key: D4 Value: UpdatedData for D4
Data key: D5 Value: UpdatedData for D5

Data key: D1 Value: UpdatedData for D1
Data key: D2 Value: UpdatedData for D2
Data key: D3 Value: UpdatedData for D3
Data key: D4 Value: UpdatedData for D4
Data key: D5 Value: UpdatedData for D5

You can't change values associated with keys in a map, you can only reassign values.您不能更改与地图中的键关联的值,只能重新分配值。

This leaves you 2 possibilities:这为您留下了 2 种可能性:

  1. Store pointers in the map, so you can modify the pointed object (which is not inside the map data structure).将指针存储在地图中,以便您可以修改指向的对象(不在地图数据结构内)。

  2. Store struct values, but when you modify it, you need to reassign it to the key.存储结构值,但是当你修改它时,你需要将它重新分配给键。

1. Using pointers 1. 使用指针

Storing pointers in the map: dataManaged := map[string]*Data{}在地图中存储指针: dataManaged := map[string]*Data{}

When you "fill" the map, you can't use the loop's variable, as it gets overwritten in each iteration.当你“填充”地图时,你不能使用循环的变量,因为它在每次迭代中都会被覆盖。 Instead make a copy of it, and store the address of that copy:而是制作一个副本,并存储该副本的地址:

for _, v := range dataReceived {
    fmt.Println("Received ID:", v.ID, "Value:", v.Value)
    v2 := v
    dataManaged[v.ID] = &v2
}

Output is as expected.输出符合预期。 Try it on the Go Playground .Go Playground上尝试一下。

2. Reassigning the modified struct 2.重新分配修改后的结构

Sticking to storing struct values in the map: dataManaged := map[string]Data{}坚持在地图中存储结构值: dataManaged := map[string]Data{}

Iterating over the key-value pairs will give you copies of the values.遍历键值对将为您提供值的副本。 So after you modified the value, reassign it back:因此,在您修改值后,将其重新分配:

for m, n := range dataManaged {
    n.Value = "UpdatedData for " + n.ID
    dataManaged[m] = n
    fmt.Println("Data key:", m, "Value:", n.Value)
}

Try this one on the Go Playground .Go Playground上试试这个。

I am learning Golang and Google brought me here.我正在学习 Golang,谷歌把我带到了这里。 One way is to create a DataStore struct.一种方法是创建一个 DataStore 结构。 I came up with this [see here][1].我想出了这个[见这里][1]。 Do let me know if this is a good way to do.请让我知道这是否是一个好方法。


import (
    "fmt"
)

type Data struct {
    key   string
    value string
}

type DataStore struct {
    datastore map[string]Data
}

func newDataStore() DataStore {
    return DataStore{make(map[string]Data)}
}

/*
Puts the key and value in the DataStore.
If the key (k) already exists will replace with the provided value (v).
*/
func (ds *DataStore) put(k, v string) {
    dx := Data{key: k, value: v}
    ds.datastore[k] = dx
}

/*
Returns true, if the DataStore has the key (k)
*/
func (ds *DataStore) containsKey(k string) bool {
    if _, ok := ds.datastore[k]; ok {
        return ok
    }
    return false
}

/*
Puts the key and value in the DataStore, ONLY if the key (k) is not present.
Returns true, if the put operation is successful,
false if the key (k) ia already present in the DataStore
*/
func (ds *DataStore) putIfAbsent(k, v string) bool {
    if val, ok := ds.datastore[k]; ok {
        fmt.Println("datastore contains key: ", k, "with value =", val, " --- ", ok)
        return false
    }

    fmt.Println("datastore does not contain ", k)
    dx := Data{key: k, value: v}
    ds.datastore[k] = dx
    return true
}

/*
Returns the Data value associated with the key (k).
*/
func (ds *DataStore) get(k string) Data {
    return ds.datastore[k]
}

/*
Removes the entry for the given key(k)
*/
func (ds *DataStore) removeKey(k string) {
    delete(ds.datastore, k)
}

/*
Removes the entry for the given key(k)
*/
func (ds *DataStore) removeKeys(k ...string) {
    for _, d := range k {
        delete(ds.datastore, d)
    }
}

/*
Prints the keys and values
*/
func (ds *DataStore) print() {
    for k, v := range ds.datastore {
        fmt.Println(k, " ", v)
    }
}

func main() {
    fmt.Println("Hello, playground")
    ds := newDataStore()
    ds.print()
    ds.put("D1", "V1")
    ds.put("D2", "V2")
    ds.put("D3", "V3")  
    fmt.Println("datastore with initial values")

    ds.print()

    ds.put("D1", "UpdatedData for D1")
    ds.put("D2", "UpdatedData for D2")
    ds.put("D3", "UpdatedData for D3")
    fmt.Println("datastore with updated values")

    ds.print()
    
    fmt.Println("datastore: putIfAbsent");
    ds.putIfAbsent("D3", "Duplicate Key")
    ds.putIfAbsent("D4", "V4")
    ds.putIfAbsent("D5", "V5")
    
    fmt.Println("datastore with new values")

    result := ds.get("D1")
    fmt.Println("fetching the value for D1: result: ", result)

    testKey := "D4"
    //testKeys := [2]string{"D5", "D2"}
    
    fmt.Println("datastore: containsKey: ")

    if ok := ds.containsKey(testKey); ok {
        fmt.Println("has key ", testKey, ok)
    } else {
        fmt.Println("has no key ", testKey, ok)
    }

    ds.print()
    ds.removeKey(testKey)

    fmt.Println("afer removing ", testKey)
    ds.print()

    fmt.Println("afer removing ", "D5", "D1")
    ds.removeKeys("D5", "D1")
    ds.print()
}```



  [1]: https://play.golang.org/p/4FEGkImcCKB

The question is about struct, but I found it while searching for "how to update a key if it exists, or insert it if it doesn't exist".问题是关于 struct 的,但是我在搜索“如果键存在时如何更新键,或者如果键不存在则插入它”时找到了它。

I have a map T -> number and I want to count how many times a key occurs in an array, or slice:我有一个映射T -> number ,我想计算一个键在数组或切片中出现的次数:

    data := []int{0,0,0,1,1,2,3,3,3,3,4}
    m := make(map[int]int, 0)
    for _, val := range data {
        m[val] = m[val] + 1
    }

How it works: if the key is absent, m[val] produces the 'zero' form of the type of the map value.工作原理:如果键不存在,则m[val]生成映射值类型的“零”形式。 With numerical values, this is 0 .对于数值,这是0 Then I add 1 , and store again in the slot m[val] .然后我添加1 ,并再次存储在插槽m[val] This is perfect as the first value.这是完美的第一个值。

What happens when key does not exist:当密钥不存在时会发生什么:

1. m[val] = m[val] + 1
2. m[val] = 0 + 1
3. m[val] = 1

What happens when key exists:当key存在时会发生什么:

1. m[val] = m[val] + 1
2. m[val] = 1 + 1
3. m[val] = 2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM