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

Jinja2不使用循环如何将两个列表转换为分组聚合字典

Jinja2无循环实现IP-Region字典聚合方案

问题场景

数据转换处理时遇到逻辑看似简单但始终无法得到正确结果的需求,具体信息如下:

初始输入数据

IPs: [ 'ip1', 'ip2' ]
DICT: { 'ip1': 'reg1', 'ip2': 'reg2', 'ip3': 'reg2', 'ip4': 'reg3', ... } 

预处理操作

原本计划通过过滤器拆分两个列表简化后续操作,处理逻辑:

list1: {{ DICT | dict2items() | selectattr('key', 'in', IPs) | list | map(attribute='value') | list }}
list2: {{ DICT | dict2items() | selectattr('key', 'in', IPs) | list | map(attribute='key') | list }}

实际生成的两个列表:

list1: [ 'reg1', 'reg2', 'reg2' ]
list2: [ 'ip1', 'ip2', 'ip3']

预期输出

以下两种聚合格式均可接受:

# 格式1:单值不嵌套列表,多值嵌套列表
{ 'reg1': 'ip1', 'reg2': [ 'ip2', 'ip3' ] }
# 格式2:所有值统一嵌套列表
{ 'reg1': [ 'ip1' ], 'reg2': [ 'ip2', 'ip3' ] }

已尝试的方案&存在的问题

  • 直接通过zip转字典
    实现代码:
    {{ dict(list1 | zip(list2) | list }}
    
    输出结果为{ 'reg1': 'ip1', 'reg2': 'ip2' },重复键的后续值会被直接覆盖,无法自动聚合相同键对应的多个值。
  • 结合groupby分组后转字典
    实现代码:
    {{ dict(dict(list2 | zip(list1)) | dict2items() | groupby(attribute='value') | list ) }}
    
    输出结果为{ 'reg2': [{'key': 'ip2', 'value': 'reg2'}, {'key': 'ip3', 'value': 'reg2'}], 'reg1': [{'key': 'ip1', 'value': 'reg1'}] },分组后的值是完整的键值对对象,无法在不使用循环的前提下提取出仅包含对应IP的列表。

可行方案

完全不需要使用loop/with_items类的显式循环语法,在groupby逻辑后增加一层字段提取的map处理即可。
如果已经提前生成了list1和list2,直接用下面的写法就能得到「所有值统一为列表」的预期格式:

{{ dict(
  list1 | zip(list2) | groupby(0) | map(attribute=0) 
  | zip(
      list1 | zip(list2) | groupby(0) | map(attribute=1) 
      | map('map', attribute=1) | map('list')
    )
) }}

核心处理逻辑:

  1. 将list1(region值)和list2(IP值)打包为(region, ip)格式的元组列表
  2. 按元组第一位的region值做分组
  3. 每个分组的键为region值,值提取分组内所有元组的第二位(即IP值)组成列表
  4. 将打包好的(region, IP列表)元组转为字典,最终输出就是{ 'reg1': [ 'ip1' ], 'reg2': [ 'ip2', 'ip3' ] }格式。
    如果需要「单值不套列表、多值套列表」的格式,再加一层长度判断即可,对长度为1的列表直接取第一个元素:
{{ dict(
  list1 | zip(list2) | groupby(0) | map(attribute=0) 
  | zip(
      list1 | zip(list2) | groupby(0) | map(attribute=1) 
      | map('map', attribute=1) | map('list')
    )
) | map(lambda x: (x[0], x[1] if x[1]|length > 1 else x[1][0])) | list }}

提示:如果是在Ansible环境下使用Jinja2,默认未开启lambda支持,可以将判断逻辑替换为Ansible自带的ternary过滤器,不需要自定义函数或循环即可正常运行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 22:21:31