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

Ansible如何按device属性合并两个列表?求正确实现方式

如何用Jinja2过滤器按device属性合并两个列表?

我有两个通过API调用获取的列表,需要按device属性进行合并。以下是两个列表的打印输出:

List1

TASK [Print List1] **************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        [
            {
                "device": "LTM1_Device",
                "link": "LTM1_Link",
                "ltm_pool": "LTM1_Pool"
            },
            {
                "device": "LTM2_Device",
                "link": "LTM2_Link",
                "ltm_pool": "LTM2_Pool"
            },
            {
                "device": "LTM3_Device",
                "link": "LTM3_Link",
                "ltm_pool": "LTM3_Pool"
            }
        ]
    ]
}

List2

TASK [Print List2] ****************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        [
            {
                "device": "LTM1_Device",
                "host": "/Common/LTM1_Host1",
                "ip": "0.0.0.1",
                "port": "5555"
            },
            {
                "device": "LTM1_Device",
                "host": "/Common/LTM1_Host2",
                "ip": "0.0.0.2",
                "port": "5555"
            },
            {
                "device": "LTM2_Device",
                "host": "/Common/LTM2_Host1",
                "ip": "0.0.0.3",
                "port": "5555"
            },
            {
                "device": "LTM2_Device",
                "host": "/Common/LTM2_Host2",
                "ip": "0.0.0.4",
                "port": "5555"
            },
            {
                "device": "LTM3_Device",
                "host": "/Common/LTM3_Host1",
                "ip": "0.0.0.5",
                "port": "5555"
            },
            {
                "device": "LTM3_Device",
                "host": "/Common/LTM3_Host2",
                "ip": "0.0.0.6",
                "port": "5555"
            }
        ]
    ]
}

尝试过的调试代码

我用了以下两条debug语句,结果都不符合预期:

- name: Debug
    debug:
        msg: 
            - "{{ (list2 + list1) | groupby('device') | map('last') | map('combine') | list }}"
            - "{{ (list2 + list1) | groupby('device') | map('last') | list }}"

当前输出结果

TASK [Debug] ****************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        [
            {
                "device": "LTM1_Device",
                "host": "/Common/LTM1_Host2",
                "ip": "0.0.0.1",
                "link": "LTM1_Link",
                "ltm_pool": "LTM1_Pool",
                "port": "5555"
            },
            {
                "device": "LTM2_Device",
                "host": "/Common/LTM2_Host2",
                "ip": "0.0.0.3",
                "link": "LTM2_Link",
                "ltm_pool": "LTM2_Pool",
                "port": "5555"
            },
            {
                "device": "LTM3_Device",
                "host": "/Common/LTM2_Host2",
                "ip": "0.0.0.5",
                "link": "LTM3_Link",
                "ltm_pool": "LTM3_Pool",
                "port": "5555"
            }
        ],
        [
            [
                {
                    "device": "LTM1_Device",
                    "host": "/Common/LTM1_Host1",
                    "ip": "0.0.0.1",
                    "port": "5555"
                },
                {
                    "device": "LTM1_Device",
                    "host": "/Common/LTM1_Host2",
                    "ip": "0.0.0.2",
                    "port": "5555"
                },
                {
                    "device": "LTM1_Device",
                    "link": "LTM1_Link",
                    "ltm_pool": "LTM1_Pool"
                }
            ],
            [
                {
                    "device": "LTM2_Device",
                    "host": "/Common/LTM2_Host1",
                    "ip": "0.0.0.3",
                    "port": "5555"
                },
                {
                    "device": "LTM2_Device",
                    "host": "/Common/LTM2_Host2",
                    "ip": "0.0.0.4",
                    "port": "5555"
                },
                {
                    "device": "LTM2_Device",
                    "link": "LTM2_Link",
                    "ltm_pool": "LTM2_Pool"
                }
            ],
            [
                {
                    "device": "LTM3_Device",
                    "host": "/Common/LTM3_Host1",
                    "ip": "0.0.0.5",
                    "port": "5555"
                },
                {
                    "device": "LTM3_Device",
                    "host": "/Common/LTM3_Host2",
                    "ip": "0.0.0.6",
                    "port": "5555"
                },
                {
                    "device": "LTM3_Device",
                    "link": "LTM3_Link",
                    "ltm_pool": "LTM3_Pool"
                }
            ]
        ]
    ]
}

第一条语句会丢失List2中每个device对应的第一个host元素,第二条则将元素以嵌套列表形式分开。

期望的合并效果

我希望实现如下合并结果(不介意嵌套列表,后续可自行扁平化):

[
            [
                {
                    "device": "LTM1_Device",
                    "host": "/Common/LTM1_Host1",
                    "ip": "0.0.0.1",
                    "link": "LTM1_Link",
                    "ltm_pool": "LTM1_Pool",
                    "port": "5555"
                },
                {
                    "device": "LTM1_Device",
                    "host": "/Common/LTM1_Host2",
                    "ip": "0.0.0.2",
                    "link": "LTM1_Link",
                    "ltm_pool": "LTM1_Pool",
                    "port": "5555"
                }
            ],
            [
                {
                    "device": "LTM2_Device",
                    "host": "/Common/LTM2_Host1",
                    "ip": "0.0.0.3",
                    "link": "LTM2_Link",
                    "ltm_pool": "LTM2_Pool",
                    "port": "5555"
                },
                {
                    "device": "LTM2_Device",
                    "host": "/Common/LTM2_Host2",
                    "ip": "0.0.0.4",
                    "link": "LTM2_Link",
                    "ltm_pool": "LTM2_Pool",
                    "port": "5555"
                }
            ],
            [
                {
                    "device": "LTM3_Device",
                    "host": "/Common/LTM3_Host1",
                    "ip": "0.0.0.5",
                    "link": "LTM3_Link",
                    "ltm_pool": "LTM3_Pool",
                    "port": "5555"
                },
                {
                    "device": "LTM3_Device",
                    "host": "/Common/LTM3_Host2",
                    "ip": "0.0.0.6",
                    "link": "LTM3_Link",
                    "ltm_pool": "LTM3_Pool",
                    "port": "5555"
                }
            ]
        ]

解决方案

可以通过以下步骤实现需求:

  1. 先将List1转换为以device为键的字典,方便快速匹配对应属性:
- set_fact:
    list1_device_map: "{{ list1 | items2dict(key_name='device') }}"
  1. 对List2按device分组,然后将每组内的每个元素与字典中对应device的属性合并:
- name: 合并并分组列表
  debug:
    msg: >-
      {{ 
        list2 | groupby('device') | map('last') | 
        map('map', 'combine', list1_device_map) | 
        list 
      }}

解释

  • list1 | items2dict(key_name='device'):把List1的元素转成字典,key是device的值,value是对应的整个字典对象。
  • list2 | groupby('device') | map('last'):对List2按device分组,提取每组的元素列表。
  • map('map', 'combine', list1_device_map):对每个分组里的元素,调用combine过滤器,把元素和list1_device_map中对应device的字典合并。

这样就能得到你期望的嵌套列表结构,每个device下的所有host元素都带上了List1中的link和ltm_pool属性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 06:54:47