How to only return one match Jinja

In other languages I would normally break the loop.

Since Jinja cannot break how do I only return the first match?

{% set inputerr = False %}
{%- for state in states.input_text -%}
{% if (( state.entity_id | regex_match('^input_text.lockcode_([0-9]|[12][0-9]|30)$')) and
(state.state != 'unknown')) %}
{% set slotusercode = state.state.split(':') -%}
{% if slotusercode[1][0:4]|int() == states("input_text.lockcode_code")[0:4]|int() %}
{% set inputerr = True %}
{{inputerr}}
{%- endif %}
{%- endif %}
{%- endfor %}

Run through the full for loop but use namespace to hold the first found. Namespace will be valid both outside the for loop and inside the for loop. Here’s some sample code but you can look up the specifics in the Jinja documentation.

          message: >
            Alarm was triggered by 
            {%- set ns = namespace(found=false) -%}
            {% for state in states.binary_sensor -%}
              {% if '.dsc_' in state.entity_id and state.state == 'on' -%}
                {% if not ns.found -%} 
                  {% set ns.found = true %} 
                  {{ state_attr(state.entity_id, 'friendly_name') -}}
                {% else -%} 
                  , {{ state_attr(state.entity_id, 'friendly_name') -}} 
                {% endif -%}
              {% endif -%}
            {% endfor -%}
            {% if not ns.found %} unknown {%- endif %}

1 Like

@micque Thanks, I was looking at namespace so at least I was on the right path. I’ll give it some edits and see what I come up with.

The usual workaround for the lack of a break statement is to constrain the for-loop to execute only once. You achieve it by defining the desired condition and placing it within the for statement.

Example:

{% for h in hours if h[0] <= t <= h[1] %}
   {{h[2]}}
{% endfor %}

The for-loop will iterate only if the specified condition (if h[0] <= t <= h[1]) is satisfied. Basically, you want it to iterate only once, for the desired value you wish to extract.


From Jinja2’s documentation:

Unlike in Python, it’s not possible to break or continue in a loop. You can, however, filter the sequence during iteration, which allows you to skip items. The following example skips all the users which are hidden:

{% for user in users if not user.hidden %}
   <li>{{ user.username|e }}</li>
{% endfor %}