Je voudrais fusionner des tableaux dans YAML et les charger via ruby -
some_stuff: &some_stuff
- a
- b
- c
combined_stuff:
<<: *some_stuff
- d
- e
- f
J'aimerais avoir le tableau combiné comme [a,b,c,d,e,f]
Je reçois l'erreur: je n'ai pas trouvé la clé attendue lors de l'analyse d'un mappage de bloc
Comment fusionner des tableaux dans YAML?
list
data-structures
yaml
lfender6445
la source
la source
Réponses:
Si le but est d'exécuter une séquence de commandes shell, vous pourrez peut-être y parvenir comme suit:
Cela équivaut à:
J'ai utilisé ceci sur mon
gitlab-ci.yml
(pour répondre à @ rink.attendant.6 commentaire sur la question).Exemple de travail que nous utilisons pour prendre en charge
requirements.txt
les dépôts privés depuis gitlab:où
requirements_test.txt
contient par exemple-e git+ssh://[email protected]/example/[email protected]#egg=example
la source
Mise à jour: 2019-07-01 14:06:12
Le contexte
Cet article suppose le contexte suivant:
Problème
lfender6445 souhaite fusionner deux ou plusieurs listes dans un fichier YAML, et faire apparaître ces listes fusionnées comme une seule liste singulière une fois analysées.
Solution (solution de contournement)
Cela peut être obtenu simplement en attribuant des ancres YAML aux mappages, où les listes souhaitées apparaissent comme des éléments enfants des mappages. Il y a cependant des réserves à cela (voir "Pièges" ci-dessous).
Dans l'exemple ci-dessous, nous avons trois mappages (
list_one, list_two, list_three
) et trois ancres et alias qui font référence à ces mappages le cas échéant.Lorsque le fichier YAML est chargé dans le programme, nous obtenons la liste souhaitée, mais elle peut nécessiter une petite modification après le chargement (voir les pièges ci-dessous).
Exemple
Fichier YAML d'origine
Résultat après YAML.safe_load
Pièges
Conclusion
Cette approche permet la création de listes fusionnées en utilisant la fonction d'alias et d'ancrage de YAML.
Bien que le résultat de sortie soit une liste imbriquée de listes, celle-ci peut être facilement transformée à l'aide de la
flatten
méthode.Voir également
Mise à jour de l'approche alternative par @Anthon
Exemples de
flatten
méthodeflatten
;; Fusionner / aplatir un tableau de tableauxflatten
;; http://ruby-doc.org/core-2.2.2/Array.html#method-i-flattenflatten
;; https://softwareengineering.stackexchange.com/a/254676/23884la source
Ça ne va pas marcher:
la fusion n'est prise en charge que par les spécifications YAML pour les mappages et non pour les séquences
vous mélangez complètement les choses en ayant une clé de fusion
<<
suivie du séparateur clé / valeur:
et une valeur qui est une référence , puis continuez avec une liste au même niveau d'indentationCe n'est pas correct YAML:
Ainsi, votre exemple de syntaxe n'aurait même pas de sens en tant que proposition d'extension YAML.
Si vous souhaitez faire quelque chose comme la fusion de plusieurs tableaux, vous pouvez envisager une syntaxe telle que:
où
s1
,s2
,s3
sont des ancres sur des séquences (non représentés) que vous souhaitez fusionner dans une nouvelle séquence, puis ont lad
,e
etf
annexées à cela. Mais YAML résout d'abord ce type de profondeur de structures, il n'y a donc pas de contexte réel disponible pendant le traitement de la clé de fusion. Il n'y a pas de tableau / liste à votre disposition où vous pouvez attacher la valeur traitée (la séquence ancrée).Vous pouvez adopter l'approche proposée par @dreftymac, mais cela présente l'énorme inconvénient que vous devez en quelque sorte connaître les séquences imbriquées à aplatir (c'est-à-dire en connaissant le "chemin" de la racine de la structure de données chargée à la séquence parente), ou que vous parcouriez récursivement la structure de données chargée à la recherche de tableaux / listes imbriqués et de les aplatir tous sans discernement.
Une meilleure solution IMO serait d'utiliser des balises pour charger des structures de données qui font l'aplatissement pour vous. Cela permet d'indiquer clairement ce qui doit être aplati et ce qui ne l'est pas et vous donne un contrôle total sur si cet aplatissement est effectué pendant le chargement ou pendant l'accès. Laquelle choisir est une question de facilité de mise en œuvre et d'efficacité en termes de temps et d'espace de stockage. C'est le même compromis qui doit être fait pour implémenter la fonctionnalité de clé de fusion et il n'y a pas de solution unique qui soit toujours la meilleure.
Par exemple, ma
ruamel.yaml
bibliothèque utilise les merge-dicts de force brute lors du chargement lors de l'utilisation de son chargeur sécurisé, ce qui entraîne des dictionnaires fusionnés qui sont des dictionnaires Python normaux. Cette fusion doit être effectuée à l'avance et duplique les données (espace inefficace) mais est rapide dans la recherche de valeur. Lorsque vous utilisez le chargeur aller-retour, vous voulez pouvoir vider les fusions non fusionnées, elles doivent donc être séparées. Le dict, comme la structure de données chargée à la suite du chargement aller-retour, est peu encombrant mais plus lent d'accès, car il doit essayer de rechercher une clé qui ne se trouve pas dans le dict lui-même dans les fusions (et cela n'est pas mis en cache, donc il doit être fait à chaque fois). Bien entendu, ces considérations ne sont pas très importantes pour les fichiers de configuration relativement petits.Ce qui suit implémente un schéma de fusion pour les listes en python en utilisant des objets avec une balise
flatten
qui récursent à la volée dans des éléments qui sont des listes et des balisestoflatten
. En utilisant ces deux balises, vous pouvez avoir un fichier YAML:(l'utilisation de séquences de style flux vs bloc est complètement arbitraire et n'a aucune influence sur le résultat chargé).
Lors de l'itération sur les éléments qui sont la valeur de la clé,
m1
cela «revient» dans les séquences étiquetées avectoflatten
, mais affiche d'autres listes (aliasées ou non) comme un élément unique.Un moyen possible avec le code Python d'y parvenir est:
qui sort:
Comme vous pouvez le voir, dans la séquence à aplatir, vous pouvez soit utiliser un alias pour une séquence balisée, soit utiliser une séquence balisée. YAML ne vous permet pas de faire:
, c'est-à-dire étiqueter une séquence ancrée, car cela en ferait essentiellement une structure de données différente.
L'utilisation de balises explicites est préférable à l'OMI que de faire de la magie comme avec les clés de fusion YAML
<<
. Si rien d'autre, vous devez maintenant passer par des cerceaux si vous avez un fichier YAML avec un mappage qui a une clé<<
que vous ne voulez pas agir comme une clé de fusion, par exemple lorsque vous faites un mappage des opérateurs C à leurs descriptions en anglais (ou dans une autre langue naturelle).la source
Si vous avez seulement besoin de fusionner un élément dans une liste, vous pouvez le faire
qui donne
la source
Vous pouvez fusionner les mappages puis convertir leurs clés en liste, dans ces conditions:
la source