Merging lists of dictionaries
If you have two or more lists of dictionaries and want to combine them into a list of merged dictionaries, where the dictionaries are merged by an attribute, you can use the community.general.lists_mergeby filter.
Note
The output of the examples in this section use the YAML callback plugin. Quoting: “Ansible output that can be quite a bit easier to read than the default JSON formatting.” See the documentation for the community.general.yaml callback plugin.
Let us use the lists below in the following examples:
list1:
- {name: foo, extra: true}
- {name: bar, extra: false}
- {name: meh, extra: true}
list2:
- {name: foo, path: /foo}
- {name: baz, path: /baz}
Two lists
In the example below the lists are merged by the attribute name
:
list3: "{{ list1 |
community.general.lists_mergeby(list2, 'name') }}"
This produces:
list3:
- {name: bar, extra: false}
- {name: baz, path: /baz}
- {name: foo, extra: true, path: /foo}
- {name: meh, extra: true}
New in version 2.0.0.
List of two lists
It is possible to use a list of lists as an input of the filter:
list3: "{{ [list1, list2] |
community.general.lists_mergeby('name') }}"
This produces the same result as in the previous example:
list3:
- {name: bar, extra: false}
- {name: baz, path: /baz}
- {name: foo, extra: true, path: /foo}
- {name: meh, extra: true}
Single list
It is possible to merge single list:
list3: "{{ [list1 + list2, []] |
community.general.lists_mergeby('name') }}"
This produces the same result as in the previous example:
list3:
- {name: bar, extra: false}
- {name: baz, path: /baz}
- {name: foo, extra: true, path: /foo}
- {name: meh, extra: true}
The filter also accepts two optional parameters: recursive
and list_merge
. This is available since community.general 4.4.0.
- recursive
Is a boolean, default to
false
. Should the community.general.lists_mergeby filter recursively merge nested hashes. Note: It does not depend on the value of thehash_behaviour
setting inansible.cfg
.- list_merge
Is a string, its possible values are
replace
(default),keep
,append
,prepend
,append_rp
orprepend_rp
. It modifies the behaviour of community.general.lists_mergeby when the hashes to merge contain arrays/lists.
The examples below set recursive=true
and display the differences among all six options of list_merge
. Functionality of the parameters is exactly the same as in the filter ansible.builtin.combine. See Combining hashes/dictionaries to learn details about these options.
Let us use the lists below in the following examples
list1:
- name: myname01
param01:
x: default_value
y: default_value
list: [default_value]
- name: myname02
param01: [1, 1, 2, 3]
list2:
- name: myname01
param01:
y: patch_value
z: patch_value
list: [patch_value]
- name: myname02
param01: [3, 4, 4]
list_merge=replace (default)
Example list_merge=replace
(default):
list3: "{{ [list1, list2] |
community.general.lists_mergeby('name',
recursive=true) }}"
This produces:
list3:
- name: myname01
param01:
x: default_value
y: patch_value
list: [patch_value]
z: patch_value
- name: myname02
param01: [3, 4, 4]
list_merge=keep
Example list_merge=keep
:
list3: "{{ [list1, list2] |
community.general.lists_mergeby('name',
recursive=true,
list_merge='keep') }}"
This produces:
list3:
- name: myname01
param01:
x: default_value
y: patch_value
list: [default_value]
z: patch_value
- name: myname02
param01: [1, 1, 2, 3]
list_merge=append
Example list_merge=append
:
list3: "{{ [list1, list2] |
community.general.lists_mergeby('name',
recursive=true,
list_merge='append') }}"
This produces:
list3:
- name: myname01
param01:
x: default_value
y: patch_value
list: [default_value, patch_value]
z: patch_value
- name: myname02
param01: [1, 1, 2, 3, 3, 4, 4]
list_merge=prepend
Example list_merge=prepend
:
list3: "{{ [list1, list2] |
community.general.lists_mergeby('name',
recursive=true,
list_merge='prepend') }}"
This produces:
list3:
- name: myname01
param01:
x: default_value
y: patch_value
list: [patch_value, default_value]
z: patch_value
- name: myname02
param01: [3, 4, 4, 1, 1, 2, 3]
list_merge=append_rp
Example list_merge=append_rp
:
list3: "{{ [list1, list2] |
community.general.lists_mergeby('name',
recursive=true,
list_merge='append_rp') }}"
This produces:
list3:
- name: myname01
param01:
x: default_value
y: patch_value
list: [default_value, patch_value]
z: patch_value
- name: myname02
param01: [1, 1, 2, 3, 4, 4]
list_merge=prepend_rp
Example list_merge=prepend_rp
:
list3: "{{ [list1, list2] |
community.general.lists_mergeby('name',
recursive=true,
list_merge='prepend_rp') }}"
This produces:
list3:
- name: myname01
param01:
x: default_value
y: patch_value
list: [patch_value, default_value]
z: patch_value
- name: myname02
param01: [3, 4, 4, 1, 1, 2]