Reputation: 1208
I have two lists:
list1: [ {'a': 'name1', 'id': 'ABC'}, {'ax': 'name2', 'id': 'DEF'} ]
list2: [ {'a': 'nameX', 'id': 'XYZ'}, {'ab': 'nameY', 'id': 'DEF'} ]
I need to derive another list, list3
which should contain the elements of list1
that is not present in list2
based on the key - id
's value.
I've tried with jinja2 but not getting the desired output.
Playbook:
- 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
Output:
"list3": [
{
"a": "name1",
"id": "ABC"
},
{
"ax": "name2",
"id": "DEF"
}
]
Expected Output:
"list3": [
{
"a": "name1",
"id": "ABC"
}
]
How can I achieve this result?
Upvotes: 2
Views: 718
Reputation: 39129
You could use rejectattr
in order to reject all the id
contained in a list populated from list2
. This later list can be created using map
to extract only the id
from list2
.
All this together gives this simple task:
- set_fact:
list3: "{{ list1 | rejectattr('id', 'in', list2 | map(attribute='id')) }}"
Given the playbook:
- 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
This yields:
TASK [set_fact] ********************************************************
ok: [localhost]
TASK [debug] ***********************************************************
ok: [localhost] => {
"list3": [
{
"a": "name1",
"id": "ABC"
}
]
}
Upvotes: 2
Reputation: 2301
Just use list comprehensions like so:
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)
Output:
[{'a': 'name1', 'id': 'ABC'}]
Upvotes: 1