Gabungkan dua hierarki pemetaan daripada fail YAML, mengekalkan semua kunci

WBOY
Lepaskan: 2024-02-10 22:00:10
ke hadapan
1262 orang telah melayarinya

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

Dalam artikel ini, editor PHP Xigua akan memperkenalkan cara menggabungkan dua hierarki pemetaan daripada fail YAML dan mengekalkan semua kunci. Prosesnya sangat mudah dan hanya memerlukan penggunaan fungsi dan kaedah yang sesuai. Dengan menggabungkan dua hierarki pemetaan, kami boleh menggabungkan kunci dan nilai mereka untuk mencipta hierarki pemetaan yang lebih besar dan lebih komprehensif. Sama ada anda bekerja dengan fail konfigurasi atau pemprosesan data, penggabungan hierarki pemetaan ialah teknik yang sangat berguna. Seterusnya, kami akan membimbing anda melalui proses langkah demi langkah supaya anda boleh menguasai teknik ini dengan mudah.

Kandungan soalan

Saya sedang mengusahakan penyelesaian yang melibatkan kunci bersarang dalam fail yaml. Perisian akan membaca fail yang diluluskan dalam parameter dan memuatkannya dalam susunan kekunci dikemas kini/ditambah.

Saya mempunyai 2 fail yaml dan saya mahu menggabungkannya tanpa kehilangan sebarang kunci. Saya mahu menyusun semua profil untuk menjana satu peta tanpa mengeluarkan sebarang kekunci.

Jadi saya ada yaml 1

env: test1
template:
  app:
    database: 
      name: oracle
Salin selepas log masuk

yaml2

env: test2
template:
  app:
    database: 
      version : 12
Salin selepas log masuk

Hasil yang saya nak ialah (tempahan yaml1 - yaml2)

env: test2
template:
  app:
    database: 
      name: oracle
      version: 12
Salin selepas log masuk

Saya cuba menyalin menggunakan peta tetapi memandangkan kekunci mempunyai nama yang sama, saya mendapat

env: test2
template:
    app:
        database:
            version: 12
Salin selepas log masuk

Saya menggunakan

gopkg.in/yaml.v3 untuk membaca yaml memberikan saya antara muka[rentetan] peta{}

dan peta menggunakan salinan

package main

import (
    "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("---:\n%s\n\n", 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

}
Salin selepas log masuk

Penyelesaian

Andaikan anda ingin menggabungkan peta YAML yang dikunci oleh "template" daripada dua dokumen YAML, pelaksanaan yang agak mudah akan kelihatan seperti ini:

package main

import (
    "fmt"

    "gopkg.in/yaml.v3"
)

const data1 = `---
env: test1
template:
  app:
    database: 
      name: oracle
      foo: whatever
`

const data2 = `---
env: test2
template:
  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\n%#v\n%#v\n", a.Tmpl, b.Tmpl, mergeMapsRecursively(a.Tmpl, b.Tmpl))
}
Salin selepas log masuk

Pautan taman permainan.

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

Jika ini bukan perkara yang anda minta, saya harap contoh saya akan membawa anda ke landasan yang betul.

Atas ialah kandungan terperinci Gabungkan dua hierarki pemetaan daripada fail YAML, mengekalkan semua kunci. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!