如何根据其他字典过滤ansible中的字典

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

如何通过匹配某些键/值对来过滤基于其他字典的字典。如果使用 | 字典_1 和字典_2 具有相同的键/值对,则它可以工作。 Difference(),但如果键/值对的数量不同,则不起作用。

- name: difference of two lists
  debug:
    var: my_dict_1 | difference(my_dict_2)
  register: output

我的数据集如下

my_dict_1:
  - build: 0.0.15
    version: 15.1.4.1
    name: HD1.1
  - build: 0.0.10
    version: 15.1.2.1
    name: HD2.1
  - build: 0.0.20
    version: 15.1.3.1
    name: HD3.1
  - build: 0.0.30
    version: 16.1.3.1
    name: HD4.1
my_dict_2:
  - build: 0.0.15
    version: 15.1.4.1
  - build: 0.0.10
    version: 15.1.2.1

在比较/删除 my_dict_1 中的 my_dict_2 后,我正在寻找如下输出:

output:
  - build: 0.0.20
    version: 15.1.3.1
    name: HD3.1
  - build: 0.0.30
    version: 16.1.3.1
    name: HD4.1
filter ansible
1个回答
1
投票

还有更多选择:

  • 通过属性buildversion
  • 的组合创建索引列表
  idx_query: '[].join(`_`, [build,version])'
  idx: "{{ my_dict_2 | json_query(idx_query) }}"

给予

  idx:
  - 0.0.15_15.1.4.1
  - 0.0.10_15.1.2.1

然后,迭代列表并选择项目

    - set_fact:
        result: "{{ result + [item] }}"
      loop: "{{ my_dict_1 }}"
      when: i not in idx
      vars:
        result: []
        i: "{{ item.build }}_{{ item.version }}"

给予

  result:
    - {build: 0.0.20, name: HD3.1, version: 15.1.3.1}
    - {build: 0.0.30, name: HD4.1, version: 16.1.3.1}
  • 可以选择将索引添加到字典中,而不是在任务中进行迭代
  my_dict3: "{{ my_dict_1 | json_query(idx_query) |
                            map('community.general.dict_kv', 'idx') |
                            zip(my_dict_1) |
                            map('combine') }}"

给予

  my_dict3:
    - {build: 0.0.15, idx: 0.0.15_15.1.4.1, name: HD1.1, version: 15.1.4.1}
    - {build: 0.0.10, idx: 0.0.10_15.1.2.1, name: HD2.1, version: 15.1.2.1}
    - {build: 0.0.20, idx: 0.0.20_15.1.3.1, name: HD3.1, version: 15.1.3.1}
    - {build: 0.0.30, idx: 0.0.30_16.1.3.1, name: HD4.1, version: 16.1.3.1}

然后,拒绝列表中的索引

  result: "{{ my_dict3 | rejectattr('idx', 'in', idx) }}"

给予

  result:
    - {build: 0.0.20, idx: 0.0.20_15.1.3.1, name: HD3.1, version: 15.1.3.1}
    - {build: 0.0.30, idx: 0.0.30_16.1.3.1, name: HD4.1, version: 16.1.3.1}

如果必须从结果中删除冗余索引,请使用过滤器ansible.utils.remove_keys

result: "{{ my_dict3 | rejectattr('idx', 'in', idx) | ansible.utils.remove_keys(target=['idx']) }}"
给出相同的结果

result: - {build: 0.0.20, name: HD3.1, version: 15.1.3.1} - {build: 0.0.30, name: HD4.1, version: 16.1.3.1}


完整剧本示例

- hosts: all vars: my_dict_1: - {build: 0.0.15, name: HD1.1, version: 15.1.4.1} - {build: 0.0.10, name: HD2.1, version: 15.1.2.1} - {build: 0.0.20, name: HD3.1, version: 15.1.3.1} - {build: 0.0.30, name: HD4.1, version: 16.1.3.1} my_dict_2: - {build: 0.0.15, version: 15.1.4.1} - {build: 0.0.10, version: 15.1.2.1} idx_query: '[].join(`_`, [build,version])' idx: "{{ my_dict_2 | json_query(idx_query) }}" my_dict3: "{{ my_dict_1 | json_query(idx_query) | map('community.general.dict_kv', 'idx') | zip(my_dict_1) | map('combine') }}" result2: "{{ my_dict3 | rejectattr('idx', 'in', idx) }}" result3: "{{ my_dict3 | rejectattr('idx', 'in', idx) | ansible.utils.remove_keys(target=['idx']) }}" tasks: - debug: var: idx - set_fact: result: "{{ result + [item] }}" loop: "{{ my_dict_1 }}" when: i not in idx vars: result: [] i: "{{ item.build }}_{{ item.version }}" - debug: var: result | to_yaml - debug: var: my_dict3 | to_yaml - debug: var: result2 | to_yaml - debug: var: result3 | to_yaml

    
© www.soinside.com 2019 - 2024. All rights reserved.