Heim  >  Artikel  >  Backend-Entwicklung  >  Führen Sie zwei Zuordnungshierarchien aus YAML-Dateien zusammen und behalten Sie dabei alle Schlüssel bei

Führen Sie zwei Zuordnungshierarchien aus YAML-Dateien zusammen und behalten Sie dabei alle Schlüssel bei

WBOY
WBOYnach vorne
2024-02-10 22:00:101229Durchsuche

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

In diesem Artikel stellt der PHP-Editor Xigua vor, wie man zwei Mapping-Hierarchien aus YAML-Dateien zusammenführt und alle Schlüssel beibehält. Der Prozess ist sehr einfach und erfordert lediglich den Einsatz entsprechender Funktionen und Methoden. Durch die Zusammenführung zweier Mapping-Hierarchien können wir deren Schlüssel und Werte kombinieren, um eine größere, umfassendere Mapping-Hierarchie zu erstellen. Unabhängig davon, ob Sie mit Konfigurationsdateien oder Datenverarbeitung arbeiten, ist das Zusammenführen von Zuordnungshierarchien eine sehr nützliche Technik. Als Nächstes führen wir Sie Schritt für Schritt durch den Prozess, damit Sie diese Technik problemlos beherrschen können.

Frageninhalt

Ich arbeite an einer Lösung mit verschachtelten Schlüsseln in einer Yaml-Datei. Die Software liest die in den Parametern übergebenen Dateien und lädt sie in der Reihenfolge, in der die Schlüssel aktualisiert/hinzugefügt werden.

Ich habe 2 Yaml-Dateien und möchte sie zusammenführen, ohne Schlüssel zu verlieren. Ich möchte alle Profile stapeln, um eine einzige Karte zu erstellen, ohne Schlüssel zu entfernen.

Also ich habe Yaml 1

env: test1
template:
  app:
    database: 
      name: oracle

yaml2

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

Das gewünschte Ergebnis ist (die Reihenfolge ist yaml1 - yaml2)

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

Ich habe versucht, mithilfe einer Karte zu kopieren, aber da die Schlüssel denselben Namen haben, bin ich bei

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

Ich verwende

gopkg.in/yaml.v3 zum Lesen von Yaml stellt mir die Map[String]-Schnittstelle{}

zur Verfügung und Karte mit Kopieren

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

}

Workaround

Angenommen, Sie möchten YAML-Maps mit dem Schlüssel „template“ aus zwei YAML-Dokumenten zusammenführen. Eine ziemlich einfache Implementierung würde so aussehen:

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

Spielplatz-Link.

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

Wenn das nicht genau das ist, wonach Sie gefragt haben, hoffe ich, dass mein Beispiel Sie trotzdem auf den richtigen Weg bringt.

Das obige ist der detaillierte Inhalt vonFühren Sie zwei Zuordnungshierarchien aus YAML-Dateien zusammen und behalten Sie dabei alle Schlüssel bei. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen