Skip to content

Iterators in Jinja

Functions like rejectattr, select, and selectattr return iterators instead of creating new lists immediately. This design helps save memory by deferring computation until the iterator is consumed in a loop or converted into a list.

Converting an Iterator to a List

To consume an iterator and create a new list, simply use the | list filter.

Example

jinja
{% set directory = context.directory | json | rejectattr("virtualOnNet") | list -%}

Explanation

  • rejectattr("virtualOnNet"): Filters out items where the attribute virtualOnNet is True.
  • | list: Converts the iterator returned by rejectattr into a new list.

WARNING

Memory Consumption If your list is very large, duplicating it (as | list does) can consume significant memory. For such cases, consider using iterators directly to save resources.

Using Iterators with Multiple Conditions

You can create separate iterators with different filtering conditions to process the same list in multiple ways, without duplicating the list in memory.

Example

jinja
{% set directory = context.directory | json -%}
{% set endusers = directory | rejectattr("virtualOnNet") | selectattr("userType", "eq", "EndUser") -%}
{% set virtualusers = directory | selectattr("virtualOnNet") %}

Explanation

  • Original Data:
jinja
{% set directory = context.directory \| json -%}

The original list of dictionaries is converted from JSON.

  • End Users Iterator:
jinja
{% set endusers = directory | rejectattr("virtualOnNet") | selectattr("userType", "eq", "EndUser") -%}

rejectattr("virtualOnNet"): filters out users where virtualOnNet is True.
selectattr("userType", "eq", "EndUser"): further filters the iterator to include only users with userType equal to EndUser.

  • Virtual Users Iterator:
jinja
{% set virtualusers = directory | selectattr("virtualOnNet") %}

selectattr("virtualOnNet"): filters to include only users where virtualOnNet is True.

  • Iterating Over Results You can consume the iterators in separate loops for End Users:
jinja
{% for user in endusers %}
  {{ user | pp_dict }}
{% endfor %}

And for Virtual Users:

jinja
{% for user in virtualusers %}
  {{ user | pp_dict }}
{% endfor %}

Combining Iterators and Lists

If you need to combine multiple iterators into one list, use | list to materialize them first:

jinja
{% set all_users = (endusers | list) + (virtualusers | list) %}

Best Practices for Iterators

  • Use Iterators for Efficiency:
    • Iterators save memory and processing time when working with large datasets.
    • Avoid converting to a list unless necessary.
  • Combine Filtering:
    • Use rejectattr and selectattr together for complex filtering.
  • Debugging:
    • Use | list temporarily to inspect the contents of an iterator during development:
jinja
{{ endusers | list | pp_dict }}

Exercise: Practice Removing Attributes and Iterating

  • Removing Attributes:
    • Use the pop method to remove a specific key from a dictionary.
    • Modify the input to test behavior when the key is absent.
  • Using Iterators:
    • Use rejectattr and selectattr to filter items based on different conditions.
    • Experiment with combining filtered results into a single list.