Possible to get a union of dict_keys in a template?

I’m trying to iterate over a unique set of attributes of the from_state and to_state states, but can’t find a way to actually get this unique set without assuming that both states will have the same ones. I’ve tried:

Attributes changed: {%set attrs = list(trigger.from_state.attributes.keys()) | list(trigger.to_state.attributes.keys()) %}
{% for attr in attrs %}
  {% if trigger.from_state.attributes[attr] != trigger.to_state.attributes[attr] %}
   {{ attr }} : {{trigger.from_state.attributes[attr]}} ⇒ {{trigger.to_state.attributes[attr]}}, 
  {% endif %}
{% endfor %}

which gives:

Error rendering data template: UndefinedError: 'list' is undefined

Tried:

{%set attrs = trigger.from_state.attributes.keys() | trigger.to_state.attributes.keys() %}

which gives:

invalid template (TemplateAssertionError: no filter named 'trigger.to_state.attributes.keys') for dictionary value @ data['action'][0]['data_template']['message']. Got None.

Tried:

{%set attrs = trigger.from_state.attributes.keys().__or__(trigger.to_state.attributes.keys()) %}

which gives:

Error rendering data template: SecurityError: access to attribute '__or__' of 'dict_keys' object is unsafe.

Any suggestions?

{{ (trigger.from_state.attributes|list +
    trigger.to_state.attributes  |list)|unique|list }}

This returns a list of the unique attribute names. Not sure where you want to go from there.

I suppose if you wanted to iterate over them, then:

{% set attrs = (trigger.from_state.attributes|list +
                trigger.to_state.attributes  |list)|unique %}
{% for attr in attrs %}
   ...
{% endfor %}
1 Like

That’s exactly what I was looking for, thank you!

1 Like