Eu gostaria de mesclar arrays em YAML e carregá-los via ruby -
some_stuff: &some_stuff
- a
- b
- c
combined_stuff:
<<: *some_stuff
- d
- e
- f
Eu gostaria de ter a matriz combinada como [a,b,c,d,e,f]
Recebo o erro: não encontrei a chave esperada ao analisar um mapeamento de bloco
Como faço para mesclar matrizes em YAML?
list
data-structures
yaml
lfender6445
fonte
fonte
Respostas:
Se o objetivo é executar uma sequência de comandos shell, você pode conseguir isso da seguinte maneira:
Isso é equivalente a:
Tenho usado isso no meu
gitlab-ci.yml
(para responder ao comentário @rink.attendant.6 sobre a pergunta).Exemplo
requirements.txt
prático que usamos para oferecer suporte a repositórios privados do gitlab:onde
requirements_test.txt
contém, por exemplo-e git+ssh://[email protected]/example/[email protected]#egg=example
fonte
Atualização: 01-07-2019 14:06:12
Contexto
Esta postagem assume o seguinte contexto:
Problema
lfender6445 deseja mesclar duas ou mais listas dentro de um arquivo YAML e fazer com que essas listas mescladas apareçam como uma lista única quando analisadas.
Solução (solução alternativa)
Isso pode ser obtido simplesmente atribuindo âncoras YAML aos mapeamentos, onde as listas desejadas aparecem como elementos filho dos mapeamentos. Existem ressalvas a isso, entretanto, (veja "Armadilhas" infra).
No exemplo abaixo, temos três mapeamentos (
list_one, list_two, list_three
) e três âncoras e aliases que se referem a esses mapeamentos quando apropriado.Quando o arquivo YAML é carregado no programa, obtemos a lista que desejamos, mas pode exigir uma pequena modificação após o carregamento (veja as armadilhas abaixo).
Exemplo
Arquivo YAML original
Resultado após YAML.safe_load
Armadilhas
Conclusão
Essa abordagem permite a criação de listas mescladas usando o alias e o recurso âncora do YAML.
Embora o resultado da saída seja uma lista aninhada de listas, isso pode ser facilmente transformado usando o
flatten
método.Veja também
Abordagem alternativa atualizada por @Anthon
Exemplos do
flatten
métodoflatten
;; Mesclar / nivelar uma matriz de matrizesflatten
;; http://ruby-doc.org/core-2.2.2/Array.html#method-i-flattenflatten
;; https://softwareengineering.stackexchange.com/a/254676/23884fonte
Isto não vai funcionar:
merge só é compatível com as especificações YAML para mapeamentos e não para sequências
você está misturando completamente as coisas tendo uma chave de mesclagem
<<
seguida pelo separador de chave / valor:
e um valor que é uma referência e então continua com uma lista no mesmo nível de indentaçãoYAML incorreto:
Portanto, sua sintaxe de exemplo nem mesmo faria sentido como uma proposta de extensão YAML.
Se você deseja fazer algo como mesclar várias matrizes, pode considerar uma sintaxe como:
onde
s1
,s2
,s3
são âncoras sobre sequências (não mostrados) que você deseja mesclar em uma nova sequência e, em seguida, têm ad
,e
ef
em anexo a esse. Mas YAML está resolvendo esse tipo de profundidade de estruturas primeiro, portanto, não há contexto real disponível durante o processamento da chave de mesclagem. Não há matriz / lista disponível para você onde possa anexar o valor processado (a sequência ancorada).Você pode seguir a abordagem proposta por @dreftymac, mas isso tem a grande desvantagem de que, de alguma forma, você precisa saber quais sequências aninhadas achatar (ou seja, conhecendo o "caminho" da raiz da estrutura de dados carregada até a sequência pai), ou que você percorre recursivamente a estrutura de dados carregada procurando por arrays / listas aninhados e nivela indiscriminadamente todos eles.
A melhor solução IMO seria usar tags para carregar estruturas de dados que fazem o achatamento para você. Isso permite denotar claramente o que precisa ser nivelado e o que não deve ser e oferece controle total sobre se esse nivelamento é feito durante o carregamento ou durante o acesso. Qual escolher é uma questão de facilidade de implementação e eficiência de tempo e espaço de armazenamento. Essa é a mesma compensação que precisa ser feita para implementar o recurso chave de mesclagem e não há uma solução única que seja sempre a melhor.
Por exemplo, minha
ruamel.yaml
biblioteca usa merge-dicts de força bruta durante o carregamento ao usar seu carregador seguro, o que resulta em dicionários combinados que são dicts normais do Python. Essa mesclagem deve ser feita antecipadamente e duplica os dados (espaço ineficiente), mas é rápida na pesquisa de valor. Ao usar o carregador de ida e volta, você deseja poder despejar as mesclagens não mescladas, portanto, elas precisam ser mantidas separadas. O dicionário, como a estrutura de dados carregado como resultado do carregamento de ida e volta, é eficiente em termos de espaço, mas mais lento no acesso, pois precisa tentar e procurar uma chave não encontrada no próprio dicionário nas mesclagens (e isso não é armazenado em cache, então precisa ser feito o tempo todo). É claro que essas considerações não são muito importantes para arquivos de configuração relativamente pequenos.O seguinte implementa um esquema de mesclagem para listas em python usando objetos com tag
flatten
que recorre em tempo real em itens que são listas e marcadostoflatten
. Usando essas duas tags, você pode ter um arquivo YAML:(o uso de sequências de estilo de fluxo vs bloco é completamente arbitrário e não tem influência no resultado carregado).
Ao iterar os itens que são o valor da chave,
m1
isso "recorre" às sequências marcadas comtoflatten
, mas exibe outras listas (com alias ou não) como um único item.Uma maneira possível com o código Python de conseguir isso é:
que produz:
Como você pode ver, na sequência que precisa ser nivelada, você pode usar um alias para uma sequência marcada ou uma sequência marcada. YAML não permite que você faça:
, ou seja, marcar uma sequência ancorada, pois isso essencialmente a transformaria em uma estrutura de dados diferente.
Usar tags explícitas é IMO melhor do que ter alguma mágica acontecendo com as teclas de mesclagem YAML
<<
. Se nada mais, você agora tem que passar por muitos obstáculos se acontecer de você ter um arquivo YAML com um mapeamento que tem uma chave<<
que você não deseja que atue como uma chave de mesclagem, por exemplo, quando você faz um mapeamento de operadores C para suas descrições em inglês (ou alguma outra língua natural).fonte
Se você só precisa mesclar um item em uma lista, você pode fazer
que produz
fonte
Você pode mesclar mapeamentos e converter suas chaves em uma lista, nas seguintes condições:
fonte