Chciałbym scalić tablice w YAML i załadować je przez ruby -
some_stuff: &some_stuff
- a
- b
- c
combined_stuff:
<<: *some_stuff
- d
- e
- f
Chciałbym mieć połączoną tablicę jako [a,b,c,d,e,f]
Otrzymuję błąd: nie znalazłem oczekiwanego klucza podczas analizowania mapowania bloku
Jak scalić tablice w YAML?
list
data-structures
yaml
lfender6445
źródło
źródło
Odpowiedzi:
Jeśli celem jest uruchomienie sekwencji poleceń powłoki, możesz to osiągnąć w następujący sposób:
Jest to równoważne z:
gitlab-ci.yml
Używałem tego na moim (aby odpowiedzieć @ rink.attendant.6 na komentarz do pytania).Przykład roboczy, którego używamy do obsługi
requirements.txt
posiadania prywatnych repozytoriów z gitlab:gdzie
requirements_test.txt
zawiera np-e git+ssh://[email protected]/example/[email protected]#egg=example
źródło
Aktualizacja: 01.07.2019 14:06:12
Kontekst
Ten post zakłada następujący kontekst:
Problem
lfender6445 chce scalić dwie lub więcej list w pliku YAML i sprawić, by te scalone listy pojawiały się jako jedna lista podczas analizowania.
Rozwiązanie (obejście)
Można to uzyskać po prostu przypisując kotwice YAML do mapowań, gdzie żądane listy pojawiają się jako elementy podrzędne mapowań. Istnieją jednak zastrzeżenia (patrz „Pułapki” poniżej).
W poniższym przykładzie mamy trzy mapowania (
list_one, list_two, list_three
) oraz trzy kotwice i aliasy, które odwołują się do tych mapowań tam, gdzie jest to stosowne.Kiedy plik YAML jest ładowany do programu, otrzymujemy listę, którą chcemy, ale może ona wymagać niewielkiej modyfikacji po załadowaniu (patrz pułapki poniżej).
Przykład
Oryginalny plik YAML
Wynik po YAML.safe_load
Pułapki
Wniosek
Takie podejście umożliwia tworzenie scalonych list przy użyciu aliasu i funkcji kotwicy YAML.
Chociaż wynikiem wyjściowym jest zagnieżdżona lista list, można ją łatwo przekształcić za pomocą tej
flatten
metody.Zobacz też
Zaktualizowano alternatywne podejście autorstwa @Anthon
Przykłady
flatten
metodyflatten
;; Scal / spłaszcz tablicę tablicflatten
;; http://ruby-doc.org/core-2.2.2/Array.html#method-i-flattenflatten
;; https://softwareengineering.stackexchange.com/a/254676/23884źródło
To nie zadziała:
scalanie jest obsługiwane tylko przez specyfikacje YAML dla mapowań, a nie dla sekwencji
całkowicie mieszasz rzeczy, mając klucz scalania,
<<
po którym następuje separator klucz / wartość:
i wartość, która jest odwołaniem, a następnie kontynuujesz pracę z listą na tym samym poziomie wcięciaTo nie jest poprawne YAML:
Więc twoja przykładowa składnia nie miałaby nawet sensu jako propozycja rozszerzenia YAML.
Jeśli chcesz zrobić coś takiego, jak scalanie wielu tablic, możesz rozważyć składnię taką jak:
gdzie
s1
,s2
,s3
są kotwice na sekwencji (nie pokazane), które chcesz połączyć w nowej sekwencji, a następnie miećd
,e
af
załączone do tego. Ale YAML najpierw rozwiązuje ten rodzaj głębi struktur, więc podczas przetwarzania klucza scalającego nie jest dostępny prawdziwy kontekst. Nie ma dostępnej tablicy / listy, do której można by dołączyć przetworzoną wartość (zakotwiczoną sekwencję).Możesz przyjąć podejście zaproponowane przez @dreftymac, ale ma to ogromną wadę, że w jakiś sposób musisz wiedzieć, które zagnieżdżone sekwencje spłaszczyć (tj. Znając "ścieżkę" od korzenia załadowanej struktury danych do sekwencji nadrzędnej), lub że rekurencyjnie przechodzisz po załadowanej strukturze danych, szukając zagnieżdżonych tablic / list i bezkrytycznie spłaszczasz je wszystkie.
Lepszym rozwiązaniem IMO byłoby użycie tagów do ładowania struktur danych, które wykonują spłaszczanie za Ciebie. Pozwala to na wyraźne oznaczenie tego, co należy spłaszczyć, a co nie oraz daje pełną kontrolę nad tym, czy spłaszczanie to odbywa się podczas ładowania, czy podczas dostępu. To, który z nich wybrać, to kwestia łatwości wdrożenia oraz wydajności w zakresie czasu i przestrzeni magazynowej. Jest to ten sam kompromis, który musi być wykonany za wdrożenie seryjnej kluczową cechę i nie ma jednego rozwiązania, które jest zawsze najlepszy.
Np. Moja
ruamel.yaml
biblioteka używa dyktowania typu brute force merge-dicts podczas ładowania, kiedy używa swojego bezpiecznego programu ładującego, co skutkuje połączonymi słownikami, które są normalnymi dyktami Pythona. To scalanie musi być wykonane z góry i powiela dane (nieefektywne pod względem miejsca), ale jest szybkie w wyszukiwaniu wartości. Korzystając z modułu ładującego w obie strony, chcesz mieć możliwość zrzucania połączeń nierozłącznych, więc należy je przechowywać oddzielnie. Dykt, podobnie jak struktura danych załadowana w wyniku ładowania w obie strony, zajmuje mało miejsca, ale jest wolniejszy w dostępie, ponieważ musi spróbować wyszukać klucz, którego nie znaleziono w samym dyktowaniu w połączeniach (i to nie jest buforowane, więc za każdym razem). Oczywiście takie względy nie są bardzo ważne w przypadku stosunkowo małych plików konfiguracyjnych.Poniższy schemat implementuje schemat scalania dla list w Pythonie przy użyciu obiektów ze znacznikami,
flatten
które w locie powracają do elementów, które są listami i oznaczanetoflatten
. Używając tych dwóch tagów możesz mieć plik YAML:(użycie sekwencji typu flow vs block jest całkowicie dowolne i nie ma wpływu na ładowany wynik).
Podczas iteracji po elementach, które są wartością klucza,
m1
to „powraca” do sekwencji oznaczonych tagiemtoflatten
, ale wyświetla inne listy (z aliasami lub bez) jako pojedynczy element.Jednym z możliwych sposobów osiągnięcia tego celu za pomocą kodu Pythona jest:
które wyjścia:
Jak widać, w sekwencji, która wymaga spłaszczenia, możesz użyć aliasu do sekwencji ze znacznikiem lub możesz użyć sekwencji ze znacznikiem. YAML nie pozwala na:
, tj. oznaczyć zakotwiczoną sekwencję, ponieważ zasadniczo uczyniłoby to inną strukturę danych.
Używanie znaczników jawnych jest lepsze w IMO niż magia, jak w przypadku kluczy scalających YAML
<<
. Jeśli nic innego, musisz teraz przechodzić przez obręcze, jeśli masz plik YAML z mapowaniem, który ma klucz<<
, którego nie chcesz zachowywać się jak klucz scalający, np. Kiedy wykonujesz mapowanie operatorów C do ich opisów w języku angielskim (lub innym języku naturalnym).źródło
Jeśli chcesz scalić tylko jedną pozycję na liście, możesz to zrobić
która daje
źródło
Możesz scalić mapowania, a następnie przekonwertować ich klucze na listę, pod następującymi warunkami:
źródło