Ansible 如何合并数组中相同公共键的重复数据项
Ansible 重复键对象数组聚合实现方法
核心适配场景
针对原数组中每个元素为单键对象、存在重复公共键的结构,将同键对应的子对象聚合为列表,最终输出无重复键的合规数组。
方案1:内置过滤器链式处理(无额外循环,执行效率最高)
直接使用Ansible核心内置的Jinja2过滤器完成全流程转换,无需额外编写循环逻辑:
--- - name: 重复键数组聚合测试 hosts: localhost gather_facts: false vars: # 与题述完全一致的原始输入结构 original_array: - key1: path: sadasdasdsa user: user1 - key1: path: nBoDuqWRRoZ3LvU1wO user: user1 - key2: path: fwefwfewfwf user: user2 - key2: path: gfdgdfg user: user2 tasks: - name: 执行聚合转换 set_fact: transformed_array: >- {{ original_array # 把每个单键对象拆为标准key-value条目 | map('dict2items') # 拍平嵌套的单层列表,形成一维条目列表 | flatten(levels=1) # 按条目的key字段分组,得到(组名, 组内条目列表)结构 | groupby('key') # 把分组结果重组为目标结构:key映射对应子对象组成的列表 | map('dict', { keys: [item.0], values: [item.1 | map(attribute='value') | list] }) | list }} - name: 输出转换结果 debug: var: transformed_array
过滤器链路逐步骤说明:
map('dict2items'):将每个单键字典元素(如{"key1": {path: xxx}})转换为[{"key": "key1", "value": {path: xxx}}]的标准条目格式flatten(levels=1):移除条目外层的冗余嵌套列表,生成可直接分组的一维序列groupby('key'):按照条目的键名(即原始的key1/key2)完成分组- 最终重组环节:将每个分组的键名作为对象键,分组下所有条目的
value值聚合成列表作为对应键的取值
方案2:循环累加实现(支持自定义加工逻辑)
如果聚合过程中需要增加数据清洗、条件过滤、字段映射等自定义逻辑,可使用循环累加的方式实现,逻辑透明可调整:
- name: 初始化空的聚合存储字典 set_fact: aggregated_store: {} - name: 遍历原始数组累加聚合结果 set_fact: aggregated_store: >- {{ aggregated_store | combine({ # 新的键值追加到对应键的列表后,首次出现的键自动初始化空列表 current_key: aggregated_store.get(current_key, []) + [current_value] }) }} loop: "{{ original_array }}" vars: # 提取每个元素的顶层键名 current_key: "{{ item.keys() | first }}" # 提取每个元素的嵌套值 current_value: "{{ item[current_key] }}" - name: 把聚合字典转换为最终数组格式 set_fact: final_array: >- {{ aggregated_store | dict2items | map('dict', {keys: [item.key], values: [item.value]}) | list }}
注意事项
- 两种方案均基于Ansible核心内置能力实现,无需安装第三方集合,兼容Ansible 2.10及以上所有版本
- 若需要对聚合后的列表做去重处理,可在组装值列表的环节追加
unique过滤器,例如item.1 | map(attribute='value') | unique | list - 题述给出的目标结构示例存在JSON语法问题:对象的取值不能直接用空大括号包裹数组,实际合法可解析的结构为键直接映射聚合后的数组,不存在多余的空大括号嵌套,以上实现均输出符合语法规范的可用结构
内容的提问来源于stack exchange,提问作者ynwasg
相关产品推荐
相关产品推荐

