Filter Ansible筛选字典列表,使其仅在一个字段中包含唯一值

Filter Ansible筛选字典列表,使其仅在一个字段中包含唯一值,filter,ansible,jinja2,Filter,Ansible,Jinja2,我有一个ansible变量中的字典列表。有些词典在字段'id和字段'name'中具有相同的值,而在其他键值对中则不同(这对我来说并不重要)。我想过滤掉所有关于'name'和'id'字段的“重复”字典 例如: [{ "name": "abc", "id": "123456", "other_key": "unimportant value" }, { "name": "abc", "id": "123456",

我有一个ansible变量中的字典列表。有些词典在字段
'id
和字段
'name'
中具有相同的值,而在其他键值对中则不同(这对我来说并不重要)。我想过滤掉所有关于
'name'
'id'
字段的“重复”字典

例如:

[{
        "name": "abc",
          "id": "123456",
   "other_key": "unimportant value"
  },
  {
        "name": "abc",
          "id": "123456",
   "other_key": "another unimportant value"
  },
  {
        "name": "bcd",
          "id": "789012",
   "other_key": "unimportant value"
  }]
预期结果:

[{
        "name": "abc",
          "id": "123456"
  },
  {
        "name": "bcd",
          "id": "789012"
  }]
如何在Ansible中实现这一点?(不一定要丢弃
'other_key'
变量,也可能只是第一次出现,这无关紧要)

我已经生成了一个唯一ID列表,其中包含:

{{ mydictionaries | map(attribute='id') | unique | list }}

但是如何使用此选项过滤字典列表?

您可以使用从地图列表中仅过滤所需的键,然后应用
唯一的
过滤器

{{ mydictionnaries | json_query('[].{"name": name, "id": id}') | unique }}
下面是概念验证剧本。请注意,在上述文档中,
json_query
要求在ansible控制器上安装
pip jmespath

---
- name: Unique filtered dictionaries list example
  hosts: localhost
  gather_facts: false

  vars:
    mydictionaries: [{"name": "abc","id": "123456","other_key": "unimportant value"},{"name": "abc","id": "123456","other_key": "another unimportant value"},{"name": "bcd","id": "789012","other_key": "unimportant value"}]

  tasks:
    - name: Filter out list as wanted
      debug:
        msg: >-
          {{
            mydictionaries
            | json_query('[].{"name": name, "id": id}')
            | unique
          }}

PLAY [Unique filtered dictionaries list example] *************************************************************************************************************************************************************************************************************************************

TASK [Filter out list as wanted] ****************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "id": "123456",
            "name": "abc"
        },
        {
            "id": "789012",
            "name": "bcd"
        }
    ]
}

PLAY RECAP **************************************************************************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
Q:“过滤掉与‘name’和‘id’字段相关的“重复”字典。”

答:假设数据存储在变量
my_list
中,我们将从
name
id
属性创建的
hash
属性添加到列表中。比如说

    - set_fact:
        my_list2: "{{ my_list2|default([]) +
                      [item|combine({'hash': (item.name ~ item.id)|hash})] }}"
      loop: "{{ my_list }}"

    - debug:
        var: my_list2
    - set_fact:
        my_list3: "{{ my_list3|default([]) +
                      [{'name': item.1.0.name, 'id': item.1.0.id}] }}"
      loop: "{{ my_list2|groupby('hash') }}"

    - debug:
        var: my_list3
给予

接下来使用过滤器并选择所需的属性。比如说

    - set_fact:
        my_list2: "{{ my_list2|default([]) +
                      [item|combine({'hash': (item.name ~ item.id)|hash})] }}"
      loop: "{{ my_list }}"

    - debug:
        var: my_list2
    - set_fact:
        my_list3: "{{ my_list3|default([]) +
                      [{'name': item.1.0.name, 'id': item.1.0.id}] }}"
      loop: "{{ my_list2|groupby('hash') }}"

    - debug:
        var: my_list3
给予


谢谢,这真是太棒了!但是,我必须删除json_查询中的引号,即
json_查询('[].{name:name,id:id}')
才能使其正常工作。谢谢,这也很有效。我选择Zeitounator的解决方案来解决当前的问题,因为它只需一步(更少的代码)。但是,您的解决方案的优点是,它也可以在ansible控制器上不依赖jmespath的情况下工作,这在许多情况下肯定很方便。这个比较复杂。除此之外,它还可以按任意键组合进行排序(例如id[0:2])。