# Filtering a complex list of dictionaries into another list of dictionaries in an efficient way

**URL:** <https://forum.ansible.com/t/filtering-a-complex-list-of-dictionaries-into-another-list-of-dictionaries-in-an-efficient-way/32029>\
**Category:** Ansible Project\
**Created:** [January 22, 2020, 6:32pm UTC](https://forum.ansible.com/t/filtering-a-complex-list-of-dictionaries-into-another-list-of-dictionaries-in-an-efficient-way/32029 "2020-01-22T18:32:56Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![actionmystique](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/actionmystique/32/1678_2.png) [@actionmystique](https://forum.ansible.com/u/actionmystique)\
**Post date:** [January 22, 2020, 6:32pm UTC](https://forum.ansible.com/t/filtering-a-complex-list-of-dictionaries-into-another-list-of-dictionaries-in-an-efficient-way/32029/1 "2020-01-22T18:32:56Z")

</div>

**ansible 2.9.4**

Let’s assume the following list of dictionaries:

`  
list:

- key1:
- ‘abc’
- ‘def’  
key2: ‘ghi’  
key3: ‘jkl’
- key1:
- ‘mno’
- ‘pqr’  
key3: ‘stu’  
key4: ‘dfg’
- key1:
- ‘vwx’
- ‘yza’  
key3: ‘okl’  
key4: ‘azel’

`

The goal is threefold:

- to extract only the records which match a regex criteria over one of the keys, for instance if “key3” contains a ‘k’.
- to keep only a selection of keys, for instance only “key1”, “key3” and “key4”, which may not always be present
- to be as efficient as possible with thousands of records

In this case, we expect the resulting list:

`  
result\_list:

- key1:
- ‘abc’
- ‘def’  
key3: ‘jkl’
- key1:
- ‘vwx’
- ‘yza’  
key3: ‘okl’  
key4: ‘azel’

`

The difficulty I’m experiencing concerns “key1” as a list.

My solution works without considering “key1”:

`

- name: Filtering a complex list of dictionaries into another list of dictionaries  
vars:  
“list”: [  
{  
“key1”: [  
“abc”,  
“def”  
],  
“key2”: “ghi”,  
“key3”: “jkl”  
},  
{  
“key1”: [  
“mno”,  
“pqr”  
],  
“key3”: “stu”,  
“key4”: “dfg”  
},  
{  
“key1”: [  
“vwx”,  
“yza”  
],  
“key3”: “okl”,  
“key4”: “azel”  
}  
]  
set\_fact:  
result\_list: “{{ result\_list|default() + [{‘key3’: item.key3, ‘key4’: item.key4|default(‘’)}] }}”  
loop: “{{ list }}”  
when: item.key3 | regex\_search(‘(^._k._$)’)

`

leads to:

`  
TASK [yang : Filtering a complex list of dictionaries into another list of dictionaries] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
task path: test.yml:133  
\<172.16.136.116\> attempting to start connection  
\<172.16.136.116\> using connection plugin network\_cli  
\<172.16.136.116\> found existing local domain socket, using it!  
\<172.16.136.116\> updating play\_context for connection  
\<172.16.136.116\>  
\<172.16.136.116\> local domain socket path is .ansible/pc/521e859c25  
ok: [TEST] =\> (item={‘key1’: [‘abc’, ‘def’], ‘key2’: ‘ghi’, ‘key3’: ‘jkl’}) =\> {  
“ansible\_facts”: {  
“result\_list”: [  
{  
“key3”: “jkl”,  
“key4”: “”  
}  
]  
},  
“ansible\_loop\_var”: “item”,  
“changed”: false,  
“item”: {  
“key1”: [  
“abc”,  
“def”  
],  
“key2”: “ghi”,  
“key3”: “jkl”  
}  
}  
skipping: [TEST] =\> (item={‘key1’: [‘mno’, ‘pqr’], ‘key3’: ‘stu’, ‘key4’: ‘dfg’}) =\> {  
“ansible\_loop\_var”: “item”,  
“changed”: false,  
“item”: {  
“key1”: [  
“mno”,  
“pqr”  
],  
“key3”: “stu”,  
“key4”: “dfg”  
},  
“skip\_reason”: “Conditional result was False”  
}  
ok: [TEST] =\> (item={‘key1’: [‘vwx’, ‘yza’], ‘key3’: ‘okl’, ‘key4’: ‘azel’}) =\> {  
“ansible\_facts”: {  
“result\_list”: [  
{  
“key3”: “jkl”,  
“key4”: “”  
},  
{  
“key3”: “okl”,  
“key4”: “azel”  
}  
]  
},  
“ansible\_loop\_var”: “item”,  
“changed”: false,  
“item”: {  
“key1”: [  
“vwx”,  
“yza”  
],  
“key3”: “okl”,  
“key4”: “azel”  
}  
}

`

How can we insert “ **key1** ” in the picture?

Also, when the list contains thousands of records, it may be less compute intensive to use ` **json_query** `, but I don’t know how to use it in this context.

---

<div class="post-metadata">

**Author:** ![vbotka](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/vbotka/32/359_2.png) [@vbotka](https://forum.ansible.com/u/vbotka)\
**Post date:** [January 22, 2020, 8:49pm UTC](https://forum.ansible.com/t/filtering-a-complex-list-of-dictionaries-into-another-list-of-dictionaries-in-an-efficient-way/32029/2 "2020-01-22T20:49:43Z")

</div>

The task below does the job

&nbsp;&nbsp;&nbsp;&nbsp;- set\_fact:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result\_list: "{{ result\_list|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default() + [  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dict(keys|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;zip(keys|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map('extract', item)|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list))] }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vars:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keys: "{{ ['key1', 'key3', 'key4']|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;intersect(item.keys()|list) }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop: "{{ list|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;selectattr('key3', 'regex', '^.\*k.\*$')|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list }}"

json\_query is not much of use here, I think. If you have any large sets'  
benchmarks I'll be interested to learn. Thank you.

HTH,

&nbsp;&nbsp;-vlado

---

<div class="post-metadata">

**Author:** ![vbotka](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/vbotka/32/359_2.png) [@vbotka](https://forum.ansible.com/u/vbotka)\
**Post date:** [January 22, 2020, 10:25pm UTC](https://forum.ansible.com/t/filtering-a-complex-list-of-dictionaries-into-another-list-of-dictionaries-in-an-efficient-way/32029/3 "2020-01-22T22:25:42Z")

</div>

Custom filter shall improve the efficiency. For example a filter to select a  
list of keys from a dictionary

&nbsp;&nbsp;$ cat filter\_plugins/dict\_utils.py  
&nbsp;&nbsp;def dict\_select\_list(d, l):  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d2 = {}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for k in l:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d2[k] = d[k]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return d2

&nbsp;&nbsp;class FilterModule(object):

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def filters(self):  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'dict\_select\_list' : dict\_select\_list  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

The task below gives the same result

&nbsp;&nbsp;&nbsp;&nbsp;- set\_fact:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result\_list: "{{ result\_list|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default() + [  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item\>dict\_select\_list(keys)] }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vars:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keys: "{{ ['key1', 'key3', 'key4']|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;intersect(item.keys()|list) }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop: "{{ list|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;selectattr('key3', 'regex', '^.\*k.\*$')|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list }}"

HTH,

&nbsp;&nbsp;-vlado

---

<div class="post-metadata">

**Author:** ![actionmystique](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/actionmystique/32/1678_2.png) [@actionmystique](https://forum.ansible.com/u/actionmystique)\
**Post date:** [January 23, 2020, 6:54pm UTC](https://forum.ansible.com/t/filtering-a-complex-list-of-dictionaries-into-another-list-of-dictionaries-in-an-efficient-way/32029/4 "2020-01-23T18:54:52Z")

</div>

fantastic! 🙂

My real use case is little more complex:

1. there are other attributes like “key1” or similar to “list” (within top-level “list”) which must be taken into account
2. the regex filter on “key3” is a little more complex (a list of logical OR)

I tried to to implement the 2 points by expanding your solution, and it works **beautifully,** despite the fact that some new keys are themselves list of dictionaries, instead of simple lists or strings.  
I used something like:

`  
…  
vars:  
keys: “{{ [‘key1’, ‘key3’, ‘key4’, ‘key5’, ‘key6’]|  
intersect(item.keys()|list) }}”

loop: “{{ list|  
selectattr(‘key3’, ‘regex’, ‘regex1|regex2|regex3’)|  
list }}”

`

Finally, is there an **online documentation** that you would recommend to learn all the necessary tools to be able to perform such great filters (the ansible documentation is very sparse on that subject)?

For instance, if I need to add another constraint like another attribute must match another regex alongside “key3” (as an logical AND), I have no clue.

---

<div class="post-metadata">

**Author:** ![vbotka](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/vbotka/32/359_2.png) [@vbotka](https://forum.ansible.com/u/vbotka)\
**Post date:** [January 23, 2020, 7:42pm UTC](https://forum.ansible.com/t/filtering-a-complex-list-of-dictionaries-into-another-list-of-dictionaries-in-an-efficient-way/32029/5 "2020-01-23T19:42:31Z")

</div>

It's possible to extend the pipe. For example

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop: "{{ list|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;selectattr('key3', 'regex', 'regex1|regex2|regex3')|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;selectattr('key4', 'defined')|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list }}"

HTH,

&nbsp;&nbsp;-vlado
