
本文详解如何在 ansible jinja2 模板中将字典(key 为字符串、value 为列表)扁平化为单个列表,并支持基于键名的条件过滤(如仅保留以 "my_" 开头的键对应列表),全程无需 python 列表推导式,纯靠 ansible 内置过滤器实现。
本文详解如何在 ansible jinja2 模板中将字典(key 为字符串、value 为列表)扁平化为单个列表,并支持基于键名的条件过滤(如仅保留以 "my_" 开头的键对应列表),全程无需 python 列表推导式,纯靠 ansible 内置过滤器实现。
在 Ansible 的变量处理场景中,常需将形如 {"my_list_a": ["a","b"], "my_list_b": ["c","d"], "other": ["e"]} 的字典结构,合并为一个统一列表(如 ["a","b","c","d"])。由于 Jinja2 在 Ansible 中不支持原生列表推导式,必须依赖其提供的过滤器链完成此类转换。核心思路分为两步:提取值 → 扁平化 →(可选)前置筛选。
✅ 基础扁平化:values() + flatten
最简洁的方式是直接调用 values() 获取字典所有值(即全部列表),再通过 flatten 过滤器递归展开:
my_combined_list: "{{ my_dict.values() | flatten }}"该表达式会将 my_dict 中每个 key 对应的 list 合并为单一列表,顺序取决于字典遍历顺序(Ansible 2.10+ 保证插入序,但若不依赖顺序则无需额外处理)。结果为:
- a - b - c - a - d - e - f
⚠️ 注意:flatten 默认仅展开一层嵌套。若 value 中存在多层嵌套列表(如 ["x", ["y", ["z"]]]),需显式指定层级:| flatten(2)。
✅ 条件筛选后扁平化:dict2items + selectattr + map + flatten
当需按 key 名规则(如仅包含 "my_" 前缀的键)过滤时,需先将字典转为 item 列表,再筛选:
allow_match: [my_]
my_combined_list: >-
{{ my_dict | dict2items
| selectattr('key', 'match', allow_match|join('|'))
| map(attribute='value')
| flatten }}- dict2items:将 {"k1": v1, "k2": v2} 转为 [{"key":"k1","value":v1}, {"key":"k2","value":v2}];
- selectattr('key', 'match', 'my_|list_'):使用正则匹配 key,allow_match|join('|') 动态生成 my_|list_ 模式(支持多前缀);
- map(attribute='value'):提取筛选后每个 item 的 value 字段(即原始列表);
- flatten:最终合并所有选中列表。
此方案严格排除 list_c,输出仅含 my_list_a 和 my_list_b 的元素:["a","b","c","a","d","e"]。
? 补充处理:去重与排序
筛选/扁平化后的列表可无缝叠加其他过滤器:
my_dedup_sorted: >-
{{ my_dict | dict2items
| selectattr('key', 'match', 'my_')
| map(attribute='value')
| flatten
| unique
| sort }}unique 去重,sort 升序排列(字符串按 ASCII),结果为 ["a","b","c","d","e"]。
? 最佳实践提示
- 性能考量:dict2items 会产生临时对象,对超大字典略增开销,但绝大多数场景无感;
- 空值安全:若某些 key 的 value 为 null 或非列表,flatten 可能报错,建议前置校验或使用 default([]);
-
调试技巧:在 debug 任务中分步验证,例如:
- debug: var=(my_dict | dict2items | selectattr('key','match','my_')) | to_nice_yaml
通过组合 dict2items、selectattr、map 和 flatten,Ansible 提供了声明式、可读性强且健壮的字典列表聚合方案——无需自定义插件,即可优雅解决动态结构数据的归一化需求。

















