Ich möchte Arrays in YAML zusammenführen und über Ruby laden -
some_stuff: &some_stuff
- a
- b
- c
combined_stuff:
<<: *some_stuff
- d
- e
- f
Ich möchte das kombinierte Array als haben [a,b,c,d,e,f]
Ich erhalte die Fehlermeldung: Beim Parsen einer Blockzuordnung wurde der erwartete Schlüssel nicht gefunden
Wie füge ich Arrays in YAML zusammen?
list
data-structures
yaml
lfender6445
quelle
quelle
Antworten:
Wenn das Ziel darin besteht, eine Folge von Shell-Befehlen auszuführen, können Sie dies möglicherweise wie folgt erreichen:
Dies entspricht:
Ich habe dies auf meinem
gitlab-ci.yml
(um @ rink.attendant.6 Kommentar zu der Frage zu beantworten) verwendet.Arbeitsbeispiel, das wir verwenden, um
requirements.txt
private Repos von gitlab zu unterstützen:wo
requirements_test.txt
enthält zB-e git+ssh://[email protected]/example/[email protected]#egg=example
quelle
Update: 2019-07-01 14:06:12
Kontext
Dieser Beitrag nimmt den folgenden Kontext an:
Problem
lfender6445 möchte zwei oder mehr Listen in einer YAML-Datei zusammenführen und diese zusammengeführten Listen beim Analysieren als eine einzige Liste anzeigen lassen.
Lösung (Problemumgehung)
Dies kann einfach durch Zuweisen von YAML-Ankern zu Zuordnungen erreicht werden, wobei die gewünschten Listen als untergeordnete Elemente der Zuordnungen angezeigt werden. Dies hat jedoch einige Einschränkungen (siehe "Fallstricke" weiter unten).
Im folgenden Beispiel haben wir drei Zuordnungen (
list_one, list_two, list_three
) und drei Anker und Aliase, die gegebenenfalls auf diese Zuordnungen verweisen.Wenn die YAML-Datei in das Programm geladen wird, erhalten wir die gewünschte Liste, die jedoch nach dem Laden möglicherweise geringfügig geändert werden muss (siehe Fallstricke unten).
Beispiel
Original YAML-Datei
Ergebnis nach YAML.safe_load
Tücken
Fazit
Dieser Ansatz ermöglicht die Erstellung zusammengeführter Listen mithilfe der Alias- und Ankerfunktion von YAML.
Obwohl das Ausgabeergebnis eine verschachtelte Liste von Listen ist, kann dies mit der
flatten
Methode leicht transformiert werden .Siehe auch
Aktualisierter alternativer Ansatz von @Anthon
Beispiele für die
flatten
Methodeflatten
;; Ein Array von Arrays zusammenführen / reduzierenflatten
;; http://ruby-doc.org/core-2.2.2/Array.html#method-i-flattenflatten
;; https://softwareengineering.stackexchange.com/a/254676/23884quelle
Das wird nicht funktionieren:
Das Zusammenführen wird nur von den YAML-Spezifikationen für Zuordnungen und nicht für Sequenzen unterstützt
Sie mischen die Dinge vollständig, indem Sie einen Zusammenführungsschlüssel
<<
gefolgt vom Schlüssel- / Werttrennzeichen:
und einem Wert als Referenz verwenden und dann mit einer Liste auf derselben Einrückungsstufe fortfahrenDies ist nicht korrekt YAML:
Ihre Beispielsyntax wäre also als YAML-Erweiterungsvorschlag nicht einmal sinnvoll.
Wenn Sie beispielsweise mehrere Arrays zusammenführen möchten, sollten Sie eine Syntax wie die folgende in Betracht ziehen:
wo
s1
,s2
,s3
sind Anker auf Sequenzen (nicht dargestellt) , dass Sie in eine neue Sequenz zu fusionieren wollen und haben dann died
,e
undf
der angehängt. YAML löst diese Art von Strukturtiefe jedoch zuerst auf, sodass während der Verarbeitung des Zusammenführungsschlüssels kein realer Kontext verfügbar ist. Es steht Ihnen kein Array / keine Liste zur Verfügung, an die Sie den verarbeiteten Wert (die verankerte Sequenz) anhängen könnten.Sie können den von @dreftymac vorgeschlagenen Ansatz wählen, dies hat jedoch den großen Nachteil, dass Sie irgendwie wissen müssen, welche verschachtelten Sequenzen abgeflacht werden sollen (dh indem Sie den "Pfad" von der Wurzel der geladenen Datenstruktur zur übergeordneten Sequenz kennen). oder dass Sie die geladene Datenstruktur rekursiv durchsuchen, nach verschachtelten Arrays / Listen suchen und diese wahllos reduzieren.
Eine bessere Lösung IMO wäre die Verwendung von Tags zum Laden von Datenstrukturen, die die Abflachung für Sie übernehmen. Auf diese Weise können Sie klar angeben, was abgeflacht werden muss und was nicht, und Sie haben die volle Kontrolle darüber, ob diese Abflachung während des Ladens oder während des Zugriffs erfolgt. Welche Sie wählen sollten, hängt von der einfachen Implementierung und der Effizienz in Bezug auf Zeit und Speicherplatz ab. Dies ist der gleiche Kompromiss , dass der Bedarf für die Umsetzung des gemacht wird merge Schlüsselmerkmal , und es gibt keine einheitliche Lösung , die immer die beste ist.
Beispielsweise verwendet meine
ruamel.yaml
Bibliothek beim Laden die Brute-Force-Merge-Dicts, wenn sie ihren Safe-Loader verwendet. Dies führt zu zusammengeführten Wörterbüchern, die normale Python-Dicts sind. Diese Zusammenführung muss im Voraus erfolgen und dupliziert Daten (Speicherplatz ineffizient), ist jedoch bei der Wertsuche schnell. Wenn Sie den Roundtrip-Loader verwenden, möchten Sie in der Lage sein, die Zusammenführungen nicht zusammengeführt zu speichern, sodass sie getrennt aufbewahrt werden müssen. Das Diktat wie eine Datenstruktur, die als Ergebnis des Round-Trip-Ladens geladen wird, ist platzsparend, aber langsamer im Zugriff, da versucht werden muss, einen Schlüssel zu suchen, der im Diktat selbst in den Zusammenführungen nicht enthalten ist (und dieser wird nicht zwischengespeichert, also ist es so) muss jedes Mal gemacht werden). Natürlich sind solche Überlegungen für relativ kleine Konfigurationsdateien nicht sehr wichtig.Im Folgenden wird ein zusammenführungsähnliches Schema für Listen in Python implementiert, bei dem Objekte mit einem Tag verwendet werden,
flatten
das im laufenden Betrieb in Elemente umgewandelt wird, die Listen und Tags sindtoflatten
. Mit diesen beiden Tags können Sie eine YAML-Datei haben:(Die Verwendung von Flow- und Block-Style-Sequenzen ist völlig willkürlich und hat keinen Einfluss auf das geladene Ergebnis.)
Beim Durchlaufen der Elemente, die den Wert für den Schlüssel darstellen,
m1
"rekursiert" dies in die mit Tags gekennzeichneten Sequenzentoflatten
, zeigt jedoch andere Listen (mit oder ohne Alias) als einzelnes Element an.Ein möglicher Weg, dies mit Python-Code zu erreichen, ist:
welche Ausgänge:
Wie Sie sehen können, können Sie in der Sequenz, die abgeflacht werden muss, entweder einen Alias für eine markierte Sequenz oder eine markierte Sequenz verwenden. YAML erlaubt dir nicht:
, dh eine verankerte Sequenz markieren, da dies im Wesentlichen zu einer anderen Datenstruktur führen würde.
Die Verwendung expliziter Tags ist IMO besser als etwas Magie wie bei YAML-Zusammenführungsschlüsseln
<<
. Wenn Sie eine YAML-Datei mit einer Zuordnung haben, die einen Schlüssel enthält<<
, den Sie nicht wie einen Zusammenführungsschlüssel verhalten möchten, müssen Sie jetzt die Rahmen durchlaufen , z. B. wenn Sie eine Zuordnung von C-Operatoren zu ihren Beschreibungen vornehmen in Englisch (oder einer anderen natürlichen Sprache).quelle
Wenn Sie nur ein Element in einer Liste zusammenführen müssen, können Sie dies tun
was ergibt
quelle
Sie können Zuordnungen zusammenführen und ihre Schlüssel dann unter folgenden Bedingungen in eine Liste konvertieren:
quelle