Using CC Variable which creates a history of states, in this case populated with playing media_players, I’d like to compare 2 history states, and output the difference.
If the difference is an extra player playing, Id like to turn_on that media_player. If the difference is 1 less, Id like to turn_off that media_player.
So Id like the diff between the 2 to be media_player.google_home_dorm_marte, and since it is one less, it needs to be turned_off.
Would this be possible in jinja templates, and if not maybe python, but then again: how?..
rationale:
I now have to stop playing all then turn on all checked players, when (un)checking players. Which is silly, because the players that are not touched, should nt have to be stopped and turned on again.
what do they look like when you print them out? Are they strings or lists? Is this one of your python scripts that populates this?
If it’s a python script, then we should change that attribute into a list. As it should be a list in the first place.
If it’s not controlled by you or it’s populated by an automation of some sort, i.e not python, then you’ll have to do some type checking to verify that it’s a string or list before using that reject method.
Ok, so this will give you unique names in both lists and filter out the similarities.
{% set a = state_attr('variable.last_active_radios','history_1') %}
{% set b = state_attr('variable.last_active_radios','history_2') %}
{% if a and b %}
{% set a = a.split(', ') if a and a.count(', ') >= 1 else [ a ] %}
{% set b = b.split(', ') if b and b.count(', ') >= 1 else [ b ] %}
{{ (a | reject('in', b) | list + b | reject('in', a) | list) | join(', ') }}
{% else %}
No differences
{% endif %}
{% set a = states('variable.last_active_radios') %}
{% set b = state_attr('variable.last_active_radios','history_1') %}
{% if a and b %}
{% set a = a.split(', ') if a and a.count(', ') >= 1 else [ a ] %}
{% set b = b.split(', ') if b and b.count(', ') >= 1 else [ b ] %}
{{ (a | reject('in', b) | list + b | reject('in', a) | list) | join(', ') }}
{% else %}
No differences
{% endif %}
to calculate the last made difference. And it is spot perfect!
Since I need the output to be entered to either the media_player.play_media command or media_player.turn_off the ‘None’ should be filtered out. would that be possible?
Also, how can I see if the filtered player is an added player, or a stopped player? As to select the correct command
About the else, I know there should be a safeguard at all times. This however is intended by you as merely pro forma? Since the variable will only be set upon change/difference. So this state would never be met?
{% set a = states('variable.last_active_radios') %}
{% set b = state_attr('variable.last_active_radios','history_1') %}
{% if a and b %}
{% set a = a.split(', ') if a and a.count(', ') >= 1 else [ a ] %}
{% set b = b.split(', ') if b and b.count(', ') >= 1 else [ b ] %}
{{ (a | reject('in', b) | list + b | reject('in', a) | list) | reject('eq', 'None') | list | join(', ') }}
{% else %}
No differences
{% endif %}
No clue what added player means. As for stopped…
{% set a = states('variable.last_active_radios') %}
{% set b = state_attr('variable.last_active_radios','history_1') %}
{% if a and b %}
{% set a = a.split(', ') if a and a.count(', ') >= 1 else [ a ] %}
{% set b = b.split(', ') if b and b.count(', ') >= 1 else [ b ] %}
{% set entity_ids = (a | reject('in', b) | list + b | reject('in', a) | list) | reject('eq', 'None') | list }}
{% set stopped = states.media_player | selectattr('entity_id','in', entity_ids) | selectattr('state','eq','stopped') | map(attribute='entity_id') | list | join(', ') %}
{{ stopped }}
{% else %}
No differences
{% endif %}
No you need to have a result, it can be an empty string or something to key off of.
What happens when they have equal lists? This will change.
sorry, my fault not explaining well enough how this is setup.
for each player I have an input_boolean. turning it on ‘adds’ the player to the list of players, turning it off, takes it out of the list. either move is a change, recorded in the variable.
so the list gets longer or shorter. if it gets shorter, a player is taken out, I want to stop that player. and vice versa for adding player and playing it.
The two lists are currently the same, but occasionally one or two of the five-digit numbers is repeated somewhere in the first array, and I’d like a template to pick those out.
I’d send screenshots of me plugging these into the formula provided in this thread, but when I do that the result just comes back blank. I assume I’m not splitting correctly, or that the square brackets are the issue. I’ve tried splitting on different characters and regex_replacing the brackets, but I can’t get any result.
Six years have passed since this topic was created. Home Assistant now supports sets which have native methods for determining difference, intersection, etc.
You currently have two lists. You can easily convert the lists to sets and then use the difference method to report what is in one set but not the other.
To understand what I have suggested, copy-paste the following template into the Template Editor and observe the results.
{% set a = set([10, 20, 30, 40, 50, 60]) %}
{% set b = set([20, 40, 60, 80]) %}
{{ a.difference(b) | list }}
{{ b.difference(a) | list }}