合并来自 YAML 文件的两个映射层次结构,保留所有键

合并来自 yaml 文件的两个映射层次结构,保留所有键

php小编西瓜在这篇文章中将要介绍如何合并来自 YAML 文件的两个映射层次结构,并保留所有键。这个过程非常简单,只需要使用适当的函数和方法即可完成。通过合并两个映射层次结构,我们可以将它们的键和值组合在一起,以创建一个更大、更全面的映射层次结构。无论您是在处理配置文件还是在进行数据处理,合并映射层次结构都是一个非常有用的技巧。接下来,我们将一步步为您介绍这个过程,让您轻松掌握这个技巧。

问题内容

我正在研究涉及 yaml 文件中的嵌套键的解决方案。软件将读取参数中传递的文件并按照更新/添加密钥的顺序加载它们。

我有 2 个 yaml 文件,我想合并它们而不丢失任何密钥。我想堆叠所有配置文件以生成单个地图而不删除任何键。

所以我有 yaml 1

env: test1template:  app:    database:       name: oracle

登录后复制

yaml2

env: test2template:  app:    database:       version : 12

登录后复制

我想要的结果是(顺序是yaml1 – yaml2)

env: test2template:  app:    database:       name: oracle      version: 12

登录后复制

我尝试使用地图进行复制,但由于键具有相同的名称,所以我最终得到了

env: test2template:    app:        database:            version: 12

登录后复制

我正在使用

用于读取 yaml 的 gopkg.in/yaml.v3 为我提供了 map[string] 接口{}

和地图使用复制

package mainimport (    "fmt"    "log"    "maps"    "os"    "path/filepath"    "gopkg.in/yaml.v3")type configuration struct {    c  m    fl []string}type m = map[string]interface{}func (c *configuration) Update(nc m) {    if c.c == nil {        c.c = nc    } else {        maps.Copy(c.c, nc)    }}func (c configuration) Print() {    d, err := yaml.Marshal(&c.c)    if err != nil {        log.Fatalf("error: %v", err)    }    fmt.Printf("---:%s", string(d))}func (c configuration) ParseDir(path string) {}func (c *configuration) LoadFromFile(filename string) {    // YAML string stored in a variable    yf, yfErr := os.ReadFile(filename)    if yfErr != nil {        log.Fatal("Error reading the file ", yfErr)    }    // Map to store the parsed YAML data    var data m    // Unmarshal the YAML string into the data map    err := yaml.Unmarshal(yf, &data)    if err != nil {        log.Fatal(err)    }    c.Update(data)}func listFiles(path string) []string {    var returnLf []string    err := filepath.Walk(path,        func(path string, info os.FileInfo, err error) error {            if err != nil {                return err            }            if info.Mode().IsRegular() {                returnLf = append(returnLf, path)            }            return nil        })    if err != nil {        log.Println(err)    }    return returnLf}

登录后复制

解决方法

假设您想要合并两个 YAML 文档中以“模板”为键的 YAML 映射,一个相当简单的实现将如下所示:

package mainimport (    "fmt"    "gopkg.in/yaml.v3")const data1 = `---env: test1template:  app:    database:       name: oracle      foo: whatever`const data2 = `---env: test2template:  app:    some_stuff: [1, 2, 3, 4]    database:       version : 12      foo: 42`type T struct {    Env  string         `yaml:"env"`    Tmpl map[string]any `yaml:"template"`}func mergeMapsRecursively(dst, src map[string]any) map[string]any {    res := make(map[string]any)    for dstKey, dstVal := range dst {        srcVal, exists := src[dstKey]        if !exists {            res[dstKey] = dstVal            continue        }        dstValMap, dstValIsMap := dstVal.(map[string]any)        srcValMap, srcValIsMap := srcVal.(map[string]any)        if dstValIsMap && srcValIsMap {            res[dstKey] = mergeMapsRecursively(dstValMap, srcValMap)        } else {            res[dstKey] = srcVal        }    }    for srcKey, srcVal := range src {        if _, exists := dst[srcKey]; !exists {            res[srcKey] = srcVal        }    }    return res}func main() {    var a, b T    if err := yaml.Unmarshal([]byte(data1), &a); err != nil {        panic(err)    }    if err := yaml.Unmarshal([]byte(data2), &b); err != nil {        panic(err)    }    fmt.Printf("%#v%#v%#v", a.Tmpl, b.Tmpl, mergeMapsRecursively(a.Tmpl, b.Tmpl))}

登录后复制

Playground 链接。

mergeMapsRecursively 函数递归地合并两个映射中存在的字段(如果它们都是映射),或者将 dst 中的值替换为 src 中的值,否则 — 就像 maps.Copy 所做的那样。

如果这不完全是您所要求的,我希望我的示例无论如何都能让您走上正轨。

以上就是合并来自 YAML 文件的两个映射层次结构,保留所有键的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2483912.html

(0)
上一篇 2025年3月4日 21:25:37
下一篇 2025年2月23日 23:21:47

AD推荐 黄金广告位招租... 更多推荐

相关推荐

发表回复

登录后才能评论