You can use only Jinja2 tests in selectattr:
http://jinja.pocoo.org/docs/2.9/templates/#builtin-tests http://docs.ansible.com/ansible/latest/playbooks_tests.html

For your example:

- debug:
    msg: "{{ item.name }}"
  with_items: "{{ network.addresses.private_man | selectattr('addr','issuperset',['1.2.3.4']) | list }}"
Answer from Konstantin Suvorov on Stack Overflow
🌐
Middleware Inventory
middlewareinventory.com › blog › ansible-selectattr-example
Ansible selectattr Example - Filter dictionary and select matching item
February 24, 2024 - Ansible selectattr filter is to select matching objects from the dictionary by applying a test across all the objects in a dictionary/sequence.
🌐
GitHub
gist.github.com › halberom › 3659c98073efcabd91ed1dec3ad63fa3
ansible - example of using selectattr to filter on attrs that are defined and true · GitHub
ansible - example of using selectattr to filter on attrs that are defined and true · Raw · 00_play.yml · This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
🌐
Packetswitch
packetswitch.co.uk › ansible-selectattr-filter
How to use Ansible 'selectattr' Filter?
September 21, 2024 - The conversion is required since the selectattr filter returns an iterable object, which needs to be converted to a list for use in a loop in Ansible. In this example, the selectattr() filter, creates a list called red_fruits that contains the entire dictionary for each red fruit, including both the name and colour attributes.
🌐
0xf8
0xf8.org › 2021 › 03 › filtering-with-ansibles-selectattr-rejectattr-when-the-tested-attribute-can-be-absent
Filtering with Ansible’s selectattr()/rejectattr() when the tested attribute can be absent – 0xf8.org
March 19, 2021 - {{ fruit | selectattr('or', 'origin', 'not', 'defined', 'origin', 'equalto', 'exotic') }} # selectattr/rejectattr do not support brackets either {{ fruit | selectattr('or'(('origin', 'not', 'defined'), ('origin', 'equalto', 'exotic'))) }}
🌐
Tailored Cloud
tailored.cloud › home › advanced list operations in ansible
Advanced list operations in Ansible. selectattr, sum, map and others.
March 16, 2018 - The problem can be solved with the following ansible code. Let’s first have a look and then I will explain it step by step: # file playbook.yml - hosts: all tasks: - set_fact: test_ip: "{{ interfaces | selectattr('name', 'match', 'eth[2-9]') | sum(attribute='ips', start=[]) | selectattr('owner', 'equalto', 'TEST') | map(attribute='ip') | list | first | default('NOT_FOUND') }}" - debug: msg: "The TEST IP is {{ test_ip }}"
🌐
Oznetnerd
oznetnerd.com › 2017 › 04 › 18 › jinja2-selectattr-filter
Jinja2 selectattr() Filter - OzNetNerd.com
April 17, 2017 - The selectattr() filter will cycle through all of the dictionaries (also known as objects) inside of “users”, looking for which ones do and do not have the “password” attribute specified.
🌐
Ansible
docs.ansible.com › projects › ansible › latest › playbook_guide › complex_data_manipulation.html
Manipulating data — Ansible Community Documentation
- hosts: all gather_facts: True vars: path: /var/lib/cache tasks: - name: The mount point for {{path}}, found using the Ansible mount facts, [-1] is the same as the 'last' filter ansible.builtin.debug: msg: "{{(ansible_facts.mounts | selectattr('mount', 'in', path) | list | sort(attribute='mount'))[-1]['mount']}}"
🌐
Ansible
docs.ansible.com › ansible › latest › playbook_guide › playbooks_tests.html
Tests — Ansible Community Documentation
vars: lacp_groups: - master: lacp0 network: 10.65.100.0/24 gateway: 10.65.100.1 dns4: - 10.65.100.10 - 10.65.100.11 interfaces: - em1 - em2 - master: lacp1 network: 10.65.120.0/24 gateway: 10.65.120.1 dns4: - 10.65.100.10 - 10.65.100.11 interfaces: - em3 - em4 tasks: - debug: msg: "{{ (lacp_groups|selectattr('interfaces', 'contains', 'em1')|first).master }}"
Find elsewhere
Top answer
1 of 2
9

Edit: I actually didn't pay enough attention to the latest edit of the existing answer from @ranjandas and the following comments. My first solution is almost similar. I guess you are more interested by the second one.


Here are 2 different ways to achieve your requirement.

  1. The first solution uses only filters available in ansible by default: rejectattr you already mentionned and its counterpart selectattr. The idea is to add two lists. The first one is made by selecting all dicts not having the type atttribute. The second one is made by selecting dict having the type attribute and rejecting those where it equals special.

  2. For the second solution, I used the json_query filter which requires pip install jmespath on the controller. As you can see below it is much more compact.

The choice is yours !

The demo playbook:

---
- name: Show not so special items
  hosts: localhost
  gather_facts: false

  vars:
    list_of_dicts:
      - name: Item1
      - name: Item2
        type: special
      - name: Item3
      - name: Item4
        type: small

  tasks:
    - name: Use select/rejectattr
      debug:
        msg: >-
          {{
            (list_of_dicts | selectattr('type', 'undefined') | list)
            +
            (list_of_dicts | selectattr('type', 'defined') | rejectattr('type', 'eq', 'special') | list)
          }}

    - name: Use json_query
      vars:
        query: "[?type != 'special']"
      debug:
        msg: "{{ list_of_dicts | json_query(query) | list }}"

Which gives:

PLAY [Show not so special items] **********************************************************************************************************************************************************************************

TASK [Use select/rejectattr] **************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "name": "Item1"
        },
        {
            "name": "Item3"
        },
        {
            "name": "Item4",
            "type": "small"
        }
    ]
}

TASK [Use json_query] *********************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "name": "Item1"
        },
        {
            "name": "Item3"
        },
        {
            "name": "Item4",
            "type": "small"
        }
    ]
}

PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
2 of 2
3

You should use rejectattr to reject items that has type undefined and use selectattr to select the items that are equalto special.

{{ list_of_dicts | rejectattr("type", "undefined") | selectattr("type", "equalto", "special") | list }}

edit:

How about combining two lists like given below? I don't know whether this is the best possible way, but it works.

{{ list_of_dicts | selectattr("type", "undefined") | list }} + {{ list_of_dicts | rejectattr("type", "undefined") | rejectattr("type", "equalto", "special") | list}}
Top answer
1 of 2
8

Is selectattr filter expecting all the dicts in the list to have the same keys?

More precisely, it is expecting all dicts in the list to have the attribute you are selecting on. If not all dict in the list have it, you will have to first filter out the items where it is not defined. This can be done with selectattr as well. (thanks @Randy for making this clearer since my initial answer).

In your situation, the json_query filter (which implements jmespath) can also do the job in sometimes a more compact manner. But it is not a core filter and requires to have the community.general collection installed.

Here are a few examples taken from your above requirements solved with both core filters and json_query solutions.

The playbook:

---
- name: "Filter data with core filters or json query"
  hosts: "localhost"
  gather_facts: false

  vars:
    # Your initial data on a single line for legibility
    test_var: [{"vm":"vm1","ip":"10.10.10.1"},{"vm":"vm2","ip":"10.10.10.2"},{"test_vm":"something","process_1":"X","process_2":"Y","process_3":"Z"},{"another_vm":"something_other"}]

  tasks:
    - name: Get objects having vm==vm1
      vars:
        msg: |-
          With core filters: {{ test_var | selectattr('vm', 'defined') | selectattr('vm', '==', 'vm1') | list }}
          With json_query: {{ test_var | json_query("[?vm=='vm1']") | list }}
      debug:
        msg: "{{ msg.split('\n') }}"

    - name: Get all objects having vm attribute
      vars:
        msg: |-
          With core filters: {{ test_var | selectattr('vm', 'defined') | list }}
          With json_query: {{ test_var | json_query("[?vm]") | list }}
      debug:
        msg: "{{ msg.split('\n') }}"

    - name: Get all objects having process_2 attribute
      vars:
        msg: |-
          With core filters: {{ test_var | selectattr('process_2', 'defined') | list }}
          With json_query: {{ test_var | json_query("[?process_2]") | list }}
      debug:
        msg: "{{ msg.split('\n') }}"

    - name: Get only a list of process_2 attributes
      vars:
        msg: |-
          With core filters: {{ test_var | selectattr('process_2', 'defined') | map(attribute='process_2') | list }}
          With json_query: {{ test_var | json_query("[].process_2") | list }}
      debug:
        msg: "{{ msg.split('\n') }}"

which gives:

PLAY [Filter data with core filters or json query] *********************************************************************

TASK [Get objects having vm==vm1] *********************************************************************
ok: [localhost] => {
    "msg": [
        "With core filters: [{'vm': 'vm1', 'ip': '10.10.10.1'}]",
        "With json_query: [{'vm': 'vm1', 'ip': '10.10.10.1'}]"
    ]
}

TASK [Get all objects having vm attribute] *********************************************************************
ok: [localhost] => {
    "msg": [
        "With core filters: [{'vm': 'vm1', 'ip': '10.10.10.1'}, {'vm': 'vm2', 'ip': '10.10.10.2'}]",
        "With json_query: [{'vm': 'vm1', 'ip': '10.10.10.1'}, {'vm': 'vm2', 'ip': '10.10.10.2'}]"
    ]
}

TASK [Get all objects having process_2 attribute] *********************************************************************
ok: [localhost] => {
    "msg": [
        "With core filters: [{'test_vm': 'something', 'process_1': 'X', 'process_2': 'Y', 'process_3': 'Z'}]",
        "With json_query: [{'test_vm': 'something', 'process_1': 'X', 'process_2': 'Y', 'process_3': 'Z'}]"
    ]
}

TASK [Get only a list of process_2 attributes] *********************************************************************
ok: [localhost] => {
    "msg": [
        "With core filters: ['Y']",
        "With json_query: ['Y']"
    ]
}

PLAY RECAP *********************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
2 of 2
8

To complement this edit of Zeitounator's answer:

More precisely, it is expecting all dicts in the list to have the attribute you are selecting on.

It is not 100% true for all filter functions, to select objects by an attribute not defined by all elements:

{{ test_var | selectattr('vm','defined') |selectattr('vm','equalto','vm1') | list }} 
🌐
Red Hat
redhat.com › en › blog › ansible-jinja-lists-dictionaries
How to work with a list of dictionaries in Ansible
selectattr() filters a sequence of objects by applying a test to the specified attribute of each object and only selecting the objects when the test succeeds. map() applies a filter on a sequence of objects or looks up an attribute.
🌐
Educative
educative.io › answers › how-to-filter-a-list-by-its-attributes-in-ansible
How to filter a list by its attributes in Ansible
The result of the previous filter is then further filtered using selectattr('gender', 'eq', 'male'), which selects only items with the gender attribute set to male. Finally, the filtered result is converted into a list and assigned to the filtered_people variable. When you run this Ansible playbook, it will print the filtered_people variable containing the filtered list of people who are older than 30 and are male.
🌐
OneUptime
oneuptime.com › home › blog › how to use the selectattr and rejectattr filters in ansible
How to Use the selectattr and rejectattr Filters in Ansible
February 21, 2026 - When you have a list of dictionaries ... based on the value of a specific attribute. The selectattr filter keeps items where an attribute passes a test, and rejectattr removes items where an attribute passes a test....
🌐
GitHub
github.com › zaki-lknr › ansible-sample › blob › master › filter › selectattr.yml
ansible-sample/filter/selectattr.yml at master · zaki-lknr/ansible-sample
contain_list: - 192.168.2.20 · - 192.168.2.10 · - 192.168.0.89 · · tasks: - name: split filter sample · debug: msg: - '{{ hosts | selectattr("name", "defined") }}' - '{{ hosts | selectattr("name", "defined") | selectattr("name", "eq", "web1") }}' - '{{ hosts | selectattr("name", "defined") | selectattr("name", "match", ".*1") }}' - '{{ hosts | selectattr("pkg", "contains", "php") }}' - '{{ hosts | selectattr("addr", "in", contain_list) }}'
Author   zaki-lknr
🌐
Ansible
docs.ansible.com › ansible › latest › collections › ansible › builtin › contains_test.html
ansible.builtin.contains test – does the list contain this element — Ansible Community Documentation
These are the values key1=value1, key2=value2 and so on in the following examples: input is ansible.builtin.contains(key1=value1, key2=value2, ...) and input is not ansible.builtin.contains(key1=value1, key2=value2, ...) # simple expression {{ listofthings is contains('this') }} # as a selector - action: module=doessomething when: (lacp_groups|selectattr('interfaces', 'contains', 'em1')|first).master vars: lacp_groups: - master: lacp0 network: 10.65.100.0/24 gateway: 10.65.100.1 dns4: - 10.65.100.10 - 10.65.100.11 interfaces: - em1 - em2 - master: lacp1 network: 10.65.120.0/24 gateway: 10.65.120.1 dns4: - 10.65.100.10 - 10.65.100.11 interfaces: - em3 - em4 ·
🌐
How to Use Linux
howtouselinux.com › home › selectattr in ansible
selectattr in Ansible - howtouselinux
October 9, 2025 - - hosts: localhost vars: users: - name: john age: 25 - name: jane age: 30 - name: bob age: 20 tasks: - name: Get users over 25 debug: var: users | selectattr('age', '>=', 25) | map(attribute='name') | list · This is an Ansible playbook that targets the localhost host, which is the machine where the playbook is being executed. The playbook defines a variable named users which is a list of dictionaries, with each dictionary containing name and age key-value pairs for a user.
🌐
Medium
lucaberton.medium.com › filter-a-list-by-its-attributes-ansible-selectattr-filter-66881fe8a825
Filter A List By Its Attributes — Ansible selectattr filter | by Luca Berton | Medium
July 28, 2023 - Filter A List By Its Attributes — Ansible selectattr filter How to list only the enabled features in a network interface using Ansible System Information (Facts) and selectattr filter. How to …