如何使用Ansible合并两个字典列表?combine及list_mergeby尝试失败
如何在Ansible中按指定字段合并两个字典列表
先修正原数据的一处错误
你提供的my_address列表中,第二个字典的键写错了(写成了number),这会导致合并后出现重复键,不符合JSON规范,正确应该改为address:
my_address: [ { "name": "abc", "address": "smith street" }, { "name": "xyz", "address": "ray street" } ]
方法一:使用community.general集合的list_mergeby过滤器
这是最直接的方法,但需要先安装第三方集合:
- 安装集合:
ansible-galaxy collection install community.general
- 正确使用过滤器(注意拼写是
list_mergeby,不是你之前写错的lists_mergby):
- name: 合并字典列表 hosts: localhost vars: my_name: - { name: "xyz", number: "123" } - { name: "abc", number: "456" } my_address: - { name: "abc", address: "smith street" } - { name: "xyz", address: "ray street" } tasks: - debug: msg: "{{ my_name | community.general.list_mergeby(my_address, 'name') }}"
该过滤器会自动按name字段匹配两个列表中的字典,合并所有键值对,重复键会以第二个列表(my_address)的值优先。
方法二:使用原生Ansible过滤器实现(无需额外集合)
如果不想依赖第三方集合,可以通过字典映射+合并的方式实现:
- name: 合并字典列表 hosts: localhost vars: my_name: - { name: "xyz", number: "123" } - { name: "abc", number: "456" } my_address: - { name: "abc", address: "smith street" } - { name: "xyz", address: "ray street" } tasks: - set_fact: merged: >- {% set name_map = my_name | items2dict(key_name='name') %} {% set address_map = my_address | items2dict(key_name='name') %} {% set all_names = name_map.keys() | union(address_map.keys()) %} [{% for name in all_names %} {{ name_map[name] | combine(address_map[name] | default({})) }}{% if not loop.last %},{% endif %} {% endfor %}] - debug: var: merged
逻辑说明:
- 将两个列表转成以
name为键的字典(name_map和address_map) - 获取所有唯一的
name值 - 遍历每个
name,合并对应字典的键值对,最终组成列表
你之前操作的错误点:
- 直接用
combine过滤列表:combine是用于合并单个字典的过滤器,对列表操作时只会合并最后一个元素,无法处理列表批量合并。 list_mergeby拼写错误:正确名称是list_mergeby,且该过滤器属于community.general集合,需要先安装才能使用。
内容的提问来源于stack exchange,提问作者Ritx
相关产品推荐
相关产品推荐

