You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ansible合并字典列表:将同name项的net字段合并为列表

Ansible字典列表分组合并:按name+region合并net字段

需求说明

现有如下字典列表:

result: [
  {
    "name": "DC1",
    "region": "EU",
    "net": "10.10.1.0"
  },
  {
    "name": "DC1",
    "region": "EU",
    "net": "10.10.2.0"
  },
  {
    "name": "DC2",
    "region": "NA",
    "net": "10.10.3.0"
  }
]

需要将其转换为:合并所有name和region相同的项,对应net字段合并为列表;若该分组仅单个项,net保留字符串格式:

[
 {
    "name": "DC1",
    "region": "EU",
    "net": ["10.10.1.0","10.10.2.0"]
  },
 {
    "name": "DC2",
    "region": "NA",
    "net": "10.10.3.0"
  }
]

原方法问题分析

你之前的Playbook逻辑错误:

  • 第一步用dict2items拆分每个字典为键值对列表,拼接后得到所有键值对的集合
  • 第二步循环去重后的键值对,生成单个键的小字典
    这种方式完全没有实现按name+region分组合并的核心逻辑,只是把所有键值对拆分散开,因此得到的结果不符合预期。

正确解决方案

利用Ansible的groupby过滤器实现分组,再对每个分组做合并处理,完整Playbook如下:

- hosts: localhost
  vars:
    result: [
      {
        "name": "DC1",
        "region": "EU",
        "net": "10.10.1.0"
      },
      {
        "name": "DC1",
        "region": "EU",
        "net": "10.10.2.0"
      },
      {
        "name": "DC2",
        "region": "NA",
        "net": "10.10.3.0"
      }
    ]
  tasks:
    - name: 按name和region组合分组
      set_fact:
        grouped_dcs: "{{ result | groupby(item => [item.name, item.region]) }}"

    - name: 生成合并后的最终列表
      set_fact:
        merged_result: "{{ merged_result | default([]) + [
          {
            'name': group_key[0],
            'region': group_key[1],
            'net': net_list | length == 1 | ternary(net_list[0], net_list)
          }
        ] }}"
      loop: "{{ grouped_dcs }}"
      vars:
        group_key: "{{ item.0 }}"
        group_items: "{{ item.1 }}"
        net_list: "{{ group_items | map(attribute='net') | list }}"

    - name: 输出结果
      debug:
        var: merged_result

步骤解释

  1. 分组:使用groupby(item => [item.name, item.region])将原列表按name和region的组合作为分组键,得到的grouped_dcs是一个列表,每个元素格式为(分组键列表, 该组的字典列表),比如(["DC1", "EU"], [{}, {}])。
  2. 合并分组:循环每个分组:
    • 从分组键中提取name和region
    • 用map(attribute='net')收集该组所有net值并转为列表
    • 通过ternary过滤器判断:若net列表长度为1,保留字符串格式;否则保留列表格式
  3. 拼接结果:将每个分组处理后的字典拼接到最终列表merged_result中。

执行结果

运行上述Playbook后,merged_result将完全符合预期格式:

merged_result:
- name: DC1
  region: EU
  net:
  - 10.10.1.0
  - 10.10.2.0
- name: DC2
  region: NA
  net: 10.10.3.0

内容的提问来源于stack exchange,提问作者Marek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 20:50:24