php小編西瓜在這篇文章中將要介紹如何合併兩個來自 YAML 檔案的映射層次結構,並保留所有按鍵。這個過程非常簡單,只需要使用適當的函數和方法來完成。透過合併兩個映射層次結構,我們可以將它們的鍵和值組合在一起,以創建一個更大、更全面的映射層次結構。無論您是在處理設定檔還是在進行資料處理,合併映射層次結構都是一個非常有用的技巧。接下來,我們將一步一步為您介紹這個過程,讓您輕鬆掌握這個技巧。
我正在研究涉及 yaml 檔案中的巢狀鍵的解決方案。軟體將讀取參數中傳遞的檔案並按照更新/新增密鑰的順序載入它們。
我有 2 個 yaml 文件,我想合併它們而不丟失任何金鑰。我想堆疊所有配置文件以生成單個地圖而不刪除任何鍵。
所以我有 yaml 1
env: test1 template: app: database: name: oracle
yaml2
env: test2 template: app: database: version : 12
我想要的結果是(順序是yaml1 - yaml2)
env: test2 template: app: database: name: oracle version: 12
我嘗試使用地圖進行複製,但由於鍵具有相同的名稱,所以我最終得到了
env: test2 template: app: database: version: 12
我正在使用
用於讀取 yaml 的 gopkg.in/yaml.v3 為我提供了 map[string] 介面{}
# 和地圖使用複製
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 }
假設您想要合併兩個 YAML 文件中以「範本」為鍵的 YAML 映射,一個相當簡單的實作將如下所示:
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)) }
mergeMapsRecursively
函數遞歸地合併兩個映射中存在的欄位(如果它們都是映射),或將dst
中的值替換為src
中的值,否則— 就像maps.Copy
所做的那樣。
如果這不完全是您所要求的,我希望我的範例無論如何都能讓您走上正軌。
以上是合併來自 YAML 檔案的兩個映射層次結構,保留所有鍵的詳細內容。更多資訊請關注PHP中文網其他相關文章!