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

Ansible:替换字典值后如何去除嵌套列表结构

问题

我有以下两个字典:

"fictional_characters": {
   "male": [
      "Donkey",
      "Humpty",
      "Piranha"
   ],
   "female": [
      "Fiona",
      "Kitty_Softpaws",
      "Diane_Foxington"
   ]
}

以及

"movie_names": {
   "Donkey": "Shrek",
   "Humpty": "Puss_in_Boots",
   "Piranha": "The_Bad_Guys",
   "Fiona": "Shrek",
   "Kitty_Softpaws": "Puss_in_Boots",
   "Diane_Foxingtin": "The_Bad_Guys"
}

我想要把fictional_characters字典中的角色名替换为movie_names字典中对应的电影名,目标结构如下:

"fictional_characters": {
   "male": [
      "Shrek",
      "Puss_in_Boots",
      "The_Bad_Guys"
   ],
   "female": [
      "Shrek",
      "Puss_in_Boots",
      "The_Bad_Guys"
   ]
}

我先将fictional_characters转换为列表:

- name: Convert fictional_characters to a list
  set_fact:
    fictional_characters_list: "{{fictional_characters | dict2items }}"

得到的结果为:

"fictional_characters_list": [
  {
    "key": "male",
    "value": [
      "Donkey",
      "Humpty",
      "Piranha"
    ]
  },
  {
    "key": "female",
    "value": [
      "Fiona",
      "Kitty_Softpaws",
      "Diane_Foxington"
    ]
  }
]

接着我用Jinja2模板进行值替换:

- name: Using Jinja to swap dict values
  set_fact:
    fict_char_movies: |
      {% for e in fictional_characters_list %}
      {{ e.key }}:
      {% for char in e.value %}
      {% if char in movie_names %}
        - {{ movie_names[char]|split(',') }}
      {% endif %}
      {% endfor %}
      {% endfor %}

- name: Print the result
  debug:
    msg: "{{ fict_char_movies | from_yaml }}"

但返回的结果存在嵌套列表,不符合预期:

"male": [
  [
    "Shrek"
  ],
  [
    "Puss_in_Boots"
  ],
  [
    "The_Bad_Guys"
  ]
],
"female": [
  [
    "Shrek"
  ],
  [
    "Puss_in_Boots"
  ],
  [
    "The_Bad_Guys"
  ]
]

请问如何修改代码去除嵌套列表,得到目标结构?

解决方法

出现嵌套列表的核心原因是使用了split(',')过滤器——movie_names中的电影名都是单个字符串,没有逗号分隔,split(',')会把单个字符串拆成仅含一个元素的列表,最终导致嵌套结构。

方法1:修改原Jinja2模板

直接去掉split(',')过滤器,输出原始电影名字符串即可,修改后的任务代码如下:

- name: Using Jinja to swap dict values
  set_fact:
    fict_char_movies: |
      {% for e in fictional_characters_list %}
      {{ e.key }}:
      {% for char in e.value %}
      {% if char in movie_names %}
        - {{ movie_names[char] }}
      {% endif %}
      {% endfor %}
      {% endfor %}

- name: Print the result
  debug:
    msg: "{{ fict_char_movies | from_yaml }}"

方法2:更简洁的字典转换方式

无需先将字典转成列表,利用Ansible内置的过滤器可以一次性完成转换,代码更精简高效:

- name: Directly map characters to movies
  set_fact:
    fictional_characters_movies: >-
      {{
        fictional_characters | dict2items | map('combine', {
          'value': item.value | map('extract', movie_names) | list
        }) | items2dict
      }}

- name: Print final result
  debug:
    var: fictional_characters_movies

该方法的逻辑:

  1. 用dict2items将原字典转换为键值对列表
  2. 对每个键值对,通过map('extract', movie_names)把角色列表映射为对应的电影名列表
  3. 用combine更新每个键值对的value字段
  4. 最后通过items2dict将处理后的键值对列表转回字典,直接得到目标结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 09:21:35