Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Gabungkan dua hierarki pemetaan daripada fail YAML, mengekalkan semua kunci

Gabungkan dua hierarki pemetaan daripada fail YAML, mengekalkan semua kunci

WBOY
WBOYke hadapan
2024-02-10 22:00:101265semak imbas

合并来自 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

yaml2

env: test2
template:
  app:
    database: 
      version : 12

Hasil yang saya nak ialah (tempahan yaml1 - yaml2)

env: test2
template:
  app:
    database: 
      name: oracle
      version: 12

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

env: test2
template:
    app:
        database:
            version: 12

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

}

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))
}

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!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam