将ansible字典列表值转换为键,将键转换为值

问题描述 投票:0回答:2

我有一个场景,我需要在 Ansible 剧本中将此字典

dict1
转换为
dict2
,如下所示

dict1 = {'a':[1,2,3],'b':[4,5,6]}

dict2 = {1: 'a', 2: 'a', 3: 'a', 4: 'b', 5: 'b', 6: 'b'}

我尝试了

with_nested
with_items
,但没能成功。

ansible ansible-2.x ansible-inventory ansible-facts ansible-template
2个回答
1
投票

更新

下面的表情

  dict2: |
    {% filter combine %}
    {% filter from_yaml %}
    {% for k,v in dict1.items() %}
    - {{ dict(v|product(k)) }}
    {% endfor %}
    {% endfilter %}
    {% endfilter %}

给予

  dict2:
    1: a
    2: a
    3: a
    4: b
    5: b
    6: b

用于测试的完整剧本示例

- hosts: all

  vars:

    dict1: {a: [1, 2, 3], b: [4, 5, 6]}
    dict2: |
      {% filter combine %}
      {% filter from_yaml %}
      {% for k,v in dict1.items() %}
      - {{ dict(v|product(k)) }}
      {% endfor %}
      {% endfilter %}
      {% endfilter %}

  tasks:

    - debug:
        var: dict2

起源

下面的set_fact给出了相同的结果

    - set_fact:
        dict2: "{{ dict2|d({})|
                   combine(dict(item.value|product([item.key]))) }}"
      loop: "{{ dict1|dict2items }}"

0
投票

有点难看,但无需在任务中使用

set_fact
即可完成工作,这使您可以自由地在任何地方声明变量(例如库存、剧本、角色默认值或变量、外部文件...)。

该解决方案使用

json_query
(需要在控制器上安装额外的集合和 pip 模块,请参阅文档),因为
items2dict
无法使用嵌套元素作为键/值引用。

解决方案中的

map('flatten')
是jmespath(
json_query
使用的库)中的“错误”的解决方法,它无法直接寻址
subelements
返回的元组:它将每个元素转换为一个可以正确索引索引的列表用于
json_query

我没有花时间看看索引是否可以像您的要求中所要求的那样转换为整数。正如原样,最后的

items2dict
将它们转换回字符串表示形式。如果这是不可接受的,您将不得不进一步搜索。

注意:下面的示例将在 ansible >= 2.10 中运行。使用旧版本时,您必须在

list
表达式中粘贴一些中间
dict2
过滤器。

剧本:

- hosts: localhost
  gather_facts: false

  vars:
    dict1: {'a':[1,2,3],'b':[4,5,6]}
    transform_q: >-
      [*].{"key": [1], "value": [0].key}
    dict2: "{{ dict1 | dict2items | subelements('value') | map('flatten')
      | json_query(transform_q) | items2dict }}"

  tasks:
    - debug:
        var: dict2

给予:

PLAY [localhost] *******************************************************************************************

TASK [debug] ***********************************************************************************************
ok: [localhost] => {
    "dict2": {
        "1": "a",
        "2": "a",
        "3": "a",
        "4": "b",
        "5": "b",
        "6": "b"
    }
}

PLAY RECAP *************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
© www.soinside.com 2019 - 2024. All rights reserved.