Converting the result of a FOR loop into a LIST

Good evening,

I have a list consisting of usr_id, person.xxx and device.tracker
I want to convert the usr_id to person (empty if no person found) and save the result in a list.

I then intend to clean up the list of duplicates

Here’s what I’ve managed to do

{% set results = ["217ffba96147457cb2ea7c63c22b9111",
"17c301b6582d4151a8e966bfd4a28111",
"217ffba96147457cb2ea7c63c22b9111",
"5e4c594a2e154f7888fe3ba9b5d73111",
"person.joel",
"device_tracker.s23_de_joel"]
%}

{%- for result in results %}
{%- if states.person | selectattr("attributes.user_id", "==", result) | first != null %} 
person.{{ states.person
| selectattr("attributes.user_id", "==", result)
| map(attribute="attributes.id")
| first }}
{%- elif 'person' in result or 'device_tracker' in result %}
{{result}}
{%- endif %}
{%- endfor %}

Returns the following result. The second entry in the list was not found as usr_id, so it is deleted

person.joel
person.joel
person.nina
person.joel
device_tracker.s23_de_joel

I’m missing the penultimate step where I save the result in a list. The last cleaning step should be easier to implement

To extract data out of a loop you would use a namespace, but I would avoid the loop altogether for this case since the two “types” are easily distinguishable.

{% set results = ["217ffba96147457cb2ea7c63c22b9111",
"17c301b6582d4151a8e966bfd4a28111",
"217ffba96147457cb2ea7c63c22b9111",
"5e4c594a2e154f7888fe3ba9b5d73111",
"person.joel",
"device_tracker.s23_de_joel"] %}

{% set non_id = results | select('match', 'person|device_tracker') | list %}
{% set id = results | reject('search', '\.') | list %}
{% set id_people = states.person 
| selectattr('attributes.user_id', 'in', id) 
| map(attribute='entity_id') | list %}

{{ (non_id + id_people) | unique | list }}
Namespace version... if you just prefer loops
{% set results = ["217ffba96147457cb2ea7c63c22b9111",
"17c301b6582d4151a8e966bfd4a28111",
"217ffba96147457cb2ea7c63c22b9111",
"5e4c594a2e154f7888fe3ba9b5d73111",
"person.joel",
"device_tracker.s23_de_joel"] %}

{% set ns = namespace(people=[]) %}
{%- for result in results %}
  {%- if states.person | selectattr("attributes.user_id", "==", result) | first != null %} 
    {% set person = states.person | selectattr("attributes.user_id", "==", result)
    | map(attribute="entity_id") | first %}
    {% set ns.people = ns.people + [person] %}
  {%- elif 'person' in result or 'device_tracker' in result %}
    {% set ns.people = ns.people + [result] %}
  {%- endif %}
{%- endfor %}
{{ ns.people | unique | list }}
1 Like

Thank you for your time,

Your method is much more elegant. Generating several clean lists and then assembling them is so much cleaner than working on the original list with a loop.

I’m amazed

Thanks to your help, here’s the finished template. This is a brick for targeting the device or person to be notified

{# Si vide, extraction de tout les mobile_app #}
{% if personnes == '' or personnes is not defined %}
  {{ integration_entities('mobile_app') 
  | select('match','device_tracker')
  | list }}
{% else %}
  {# Convertion chaine en liste #}
  {% if personnes.entity_id is string %}
    {% set personnes = { 'entity_id': [personnes.entity_id]} %}
  {% endif %}
  {# Récupération des person et device_tracker en liste #}
  {% set non_id = personnes.entity_id | select('match', 'person|device_tracker') | list %}
  {# Conversion des usr_id en person #}
  {% set id = personnes.entity_id | reject('search', '\.') | list %}
  {% set id_people = states.person 
  | selectattr('attributes.user_id', 'in', id) 
  | map(attribute='entity_id') | list %}
  {# Définition liste de person et device_tracker sans doublon #}
  {{ (non_id + id_people) | unique | list }}
{% endif %}

It processes a list randomly composed of usr_id, person and device_tracker
If the list is empty, all notifiable devices are extracted

I use the person and device_tracker objects to evaluate the distance to a zone

To notify them, I use another part of the template
Info: {{cible_tmp}} is one of the elements in the {{cible}} list

{# Conversion de person en mobile_app #}
{% if 'person.' in cible_tmp %}
{{ expand(cible_tmp)
| map(attribute='attributes.source')
| list
| join
| replace('device_tracker.', 'mobile_app_') }}
{# Conversion de device_tracker avec GPS en mobile_app #}
{% elif 'device_tracker.' in cible_tmp and (state_attr(cible_tmp,'gps_accuracy') or 0 ) > 0 %}
mobile_app_{{ state_attr(cible_tmp,'friendly_name') | slugify }}
{# Déjà un mobile_app #}
{% elif 'mobile_app_' in cible_tmp %}
{{ cible_tmp }}
{# Les autres cas sont ignoré #}
{% endif %}

Then I send the message

alias: Envoie une notification ciblé
service: notify.{{device_name}}
data:
  title: "{{titre}}"
  message: "{{message}}"
  data:
    tag: "{{tag}}"
    sticky: "{{colle}}"
    persistent: "{{persistant}}"
    notification_icon: "{{icone}}"
    color: "{{couleur}}"
    icon_url: "{{illustration}}"
    clickAction: "{{click}}"
    subject: "{{resume}}"
    actions: "{{actions}}"

Hopefully this set of code will give some ideas to other users