How to merge YAML arrays?

I would like to merge arrays in YAML, and load them via ruby -

some_stuff: &some_stuff
 - a
 - b
 - c

combined_stuff:
  <<: *some_stuff
  - d
  - e
  - f

I'd like to have the combined array as [a,b,c,d,e,f]

I receive the error: did not find expected key while parsing a block mapping

How do I merge arrays in YAML?


If the aim is to run a sequence of shell commands, you may be able to achieve this as follows:

# note: no dash before commands
some_stuff: &some_stuff |-
    a
    b
    c

combined_stuff:
  - *some_stuff
  - d
  - e
  - f

This is equivalent to:

some_stuff: "a\nb\nc"

combined_stuff:
  - "a\nb\nc"
  - d
  - e
  - f

I have been using this on my gitlab-ci.yml (to answer @rink.attendant.6 comment on the question).


Working example that we use to support requirements.txt having private repos from gitlab:

.pip_git: &pip_git
- git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com".insteadOf "ssh://[email protected]"
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts

test:
    image: python:3.7.3
    stage: test
    script:
        - *pip_git
        - pip install -q -r requirements_test.txt
        - python -m unittest discover tests

use the same `*pip_git` on e.g. build image...

where requirements_test.txt contains e.g.

-e git+ssh://[email protected]/example/[email protected]#egg=example


Update: 2019-07-01 14:06:12

  • Note: another answer to this question was substantially edited with an update on alternative approaches.
    • That updated answer mentions an alternative to the workaround in this answer. It has been added to the See also section below.

Context

This post assumes the following context:

  • python 2.7
  • python YAML parser

Problem

lfender6445 wishes to merge two or more lists within a YAML file, and have those merged lists appear as one singular list when parsed.

Solution (Workaround)

This may be obtained simply by assigning YAML anchors to mappings, where the desired lists appear as child elements of the mappings. There are caveats to this, however, (see "Pitfalls" infra).

In the example below we have three mappings (list_one, list_two, list_three) and three anchors and aliases that refer to these mappings where appropriate.

When the YAML file is loaded in the program we get the list we want, but it may require a little modification after load (see pitfalls below).

Example

Original YAML file

  list_one: &id001
   - a
   - b
   - c

  list_two: &id002
   - e
   - f
   - g

  list_three: &id003
   - h
   - i
   - j

  list_combined:
      - *id001
      - *id002
      - *id003

Result after YAML.safe_load

## list_combined
  [
    [
      "a",
      "b",
      "c"
    ],
    [
      "e",
      "f",
      "g"
    ],
    [
      "h",
      "i",
      "j"
    ]
  ]

Pitfalls

  • this approach produces a nested list of lists, which may not be the exact desired output, but this can be post-processed using the flatten method
  • the usual caveats to YAML anchors and aliases apply for uniqueness and declaration order

Conclusion

This approach allows creation of merged lists by use of the alias and anchor feature of YAML.

Although the output result is a nested list of lists, this can be easily transformed using the flatten method.

See also

Updated alternative approach by @Anthon

  • See alternative approach

Examples of the flatten method

  • Javascript flatten ;; Merge/flatten an array of arrays
  • Ruby flatten ;; http://ruby-doc.org/core-2.2.2/Array.html#method-i-flatten
  • Python flatten ;; https://softwareengineering.stackexchange.com/a/254676/23884