Ansible根据键获取唯一的字典列表

Ansible get unique list of dictionaries based on a key

我有两个列表:

list1: [ {'a': 'name1', 'id': 'ABC'}, {'ax': 'name2', 'id': 'DEF'} ]
list2: [ {'a': 'nameX', 'id': 'XYZ'}, {'ab': 'nameY', 'id': 'DEF'} ]

我需要派生另一个列表,list3,它应该包含 list1 中不存在的元素 list2 基于键 - id's值。

我试过使用 jinja2 但没有得到想要的输出。

剧本:

- name: test
  hosts: localhost
  connection: local
  vars:
  - list1: [ {'a': 'name1', 'id': 'ABC'}, {'ax': 'name2', 'id': 'DEF'} ]
  - list2: [ {'a': 'nameX', 'id': 'XYZ'}, {'ab': 'nameY', 'id': 'DEF'} ]

  gather_facts: False
  tasks:
  - set_fact:
      list3: |-
        {%- set dL = [] -%}
        {%- for i in list1 -%}
          {%- for j in list2 -%}
            {%- if (i['id'] != j['id']) and (i not in dL) -%}
              {{- dL.append(i) -}}
            {%- endif -%}
          {%- endfor -%}
        {%- endfor -%}
        {{- dL -}}

  - debug: var=list3

输出:

"list3": [
    {
        "a": "name1",
        "id": "ABC"
    },
    {
        "ax": "name2",
        "id": "DEF"
    }
]

预期输出:

"list3": [
    {
        "a": "name1",
        "id": "ABC"
    }
]

我怎样才能达到这个结果?

像这样使用列表理解:

list1 = [ {'a': 'name1', 'id': 'ABC'}, {'ax': 'name2', 'id': 'DEF'} ]
list2 = [ {'a': 'nameX', 'id': 'XYZ'}, {'ab': 'nameY', 'id': 'DEF'} ]
key = 'id'
l2vals = [d[key] for d in list2]
list3 = [d for d in list1 if d[key] not in l2vals]
print(list3)

输出:

[{'a': 'name1', 'id': 'ABC'}]

您可以使用 rejectattr in order to reject all the id contained in a list populated from list2. This later list can be created using maplist2 中仅提取 id

所有这一切一起完成了这个简单的任务:

- set_fact:
    list3: "{{ list1 | rejectattr('id', 'in', list2 | map(attribute='id')) }}"

鉴于剧本:

- hosts: localhost
  gather_facts: no

  tasks:
    - set_fact:
        list3: "{{ list1 | rejectattr('id', 'in', list2 | map(attribute='id')) }}"
      vars:
        list1: [ {'a': 'name1', 'id': 'ABC'}, {'ax': 'name2', 'id': 'DEF'} ]
        list2: [ {'a': 'nameX', 'id': 'XYZ'}, {'ab': 'nameY', 'id': 'DEF'} ]

    - debug: 
        var: list3

这产生:

TASK [set_fact] ********************************************************
ok: [localhost]

TASK [debug] ***********************************************************
ok: [localhost] => {
    "list3": [
        {
            "a": "name1",
            "id": "ABC"
        }
    ]
}