如何深拷贝一张地图,然后清除原图?

新手上路,请多包涵

我正在尝试将地图( amap aSuperMap )中,然后清除 amap 下一次迭代/循环。问题是如果不 清除它在超级地图中的引用,您就无法清除地图。这是一些伪代码。

 for something := range fruits{
        aMap := make(map[string]aStruct)
        aSuperMap := make(map[string]map[string]aStruct)

        for x := range something{
            aMap[x] = aData
            aSuperMap[y] = aMap
            delete(aMap, x)
    }
//save aSuperMap
  saveASuperMap(something)

}

我也尝试过一些动态的东西,但显然它会抛出一个错误(无法分配给 nil)

 aSuperMap[y][x] = aData

问题是如何创建关联映射?在 PHP 中,我只使用 aSuperMap[y][x] = aData。似乎golang没有任何明显的方法。如果我删除 delete(aMap, x) 它在超级地图中的引用也会被删除。如果我不删除它,超级地图将以重复数据结束。基本上在每个循环中它得到 aMap 新值加上所有旧值。

原文由 The user with no hat 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 319
2 个回答

您不是在复制地图,而是在复制地图的参考。您的 delete 因此修改了原始地图和超级地图中的值。要复制地图,您必须使用 for 循环,如下所示:

 for k,v := range originalMap {
  newMap[k] = v
}

这是现已停用的 SO 文档中的示例:

 // Create the original map
originalMap := make(map[string]int)
originalMap["one"] = 1
originalMap["two"] = 2

// Create the target map
targetMap := make(map[string]int)

// Copy from the original map to the target map
for key, value := range originalMap {
  targetMap[key] = value
}

摘自 地图 - 复制地图。原作者是 JepZ 。可以在 贡献者页面 上找到署名详细信息。来源已获得 CC BY-SA 3.0 许可,可在 文档存档 中找到。参考主题ID:732,示例ID:9834。

原文由 Christian 发布,翻译遵循 CC BY-SA 3.0 许可协议

我会使用递归以防万一,这样您就可以深度复制 map 并避免在您要更改 map 元素时出现意外情况 --- map 本身。

这是 utils.go 中的示例:

 package utils

func CopyMap(m map[string]interface{}) map[string]interface{} {
    cp := make(map[string]interface{})
    for k, v := range m {
        vm, ok := v.(map[string]interface{})
        if ok {
            cp[k] = CopyMap(vm)
        } else {
            cp[k] = v
        }
    }

    return cp
}

及其测试文件(即 utils_test.go ):

 package utils

import (
    "testing"

    "github.com/stretchr/testify/require"
)

func TestCopyMap(t *testing.T) {
    m1 := map[string]interface{}{
        "a": "bbb",
        "b": map[string]interface{}{
            "c": 123,
        },
    }

    m2 := CopyMap(m1)

    m1["a"] = "zzz"
    delete(m1, "b")

    require.Equal(t, map[string]interface{}{"a": "zzz"}, m1)
    require.Equal(t, map[string]interface{}{
        "a": "bbb",
        "b": map[string]interface{}{
            "c": 123,
        },
    }, m2)
}

如果您需要 map 密钥而不是 string ,它应该很容易适应。

原文由 Francesco Casula 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题