Sort list of entities based on the numerical value of an attribute

I am trying to sort a list of entities based on the numerical value of the state attribute. The state attribute is a strong and I am not able to properly sort the list.

Another way to state the problem I am trying to solve is that I need the entity from a list on entities with the smallest numerical state value.

Are you trying to sort on the attribute value or the state value?

They are different things.

Where are you trying to sort?

In a card or a template?

Can you provide the list and what you want to sort on / use to select?

{% set x = (states.sensor 
| rejectattr('attributes.attribution', 'eq', 'Data provided by Apple iCloud')
| selectattr('attributes.device_class', 'eq', 'battery') 
| rejectattr('state', 'in', ['unavailable', 'unknown', 'discharging'])
| sort(attribute='state', reverse=true) | list) %}
{{ x }}
2 Likes

I’ve done this for finding the 2nd lowest illumance value in my house from a bunch of different light sensors,

([(states('sensor.master_bedroom_illuminance') | int(default=0)),
(states('sensor.motion_sensor_bathroom_illuminance') | int(default=0)),
(states('sensor.motion_sensor_ensuite_illuminance') | int(default=0)),
(states('sensor.motion_sensor_kitchen_illuminance') | int(default=0)),
(states('sensor.motion_sensor_powder_room_illuminance') | int(default=0)),
(states('sensor.motion_sensor_toilet_illuminance') | int(default=0))] | sort)[1]

In your case, you are sorting the values directly. I try to sort the entities based on the numerical value of their attributes.

sort(attribute='state', reverse=true)

In this case, the entities are sorted based on the string value of the ‘state’.

FYI, this is how I solved something similar (I am by no means an expert, just wanted to share if someone happens to come accross this page)

{%set nameslist = expand("sensor.elektrische_verwarming_kinderkamer_energy_power",
"sensor.elektrische_verwarming_slaapkamer_energy_power",
"sensor.elektrische_verwarming_living_energy_power")%}
{%set nameslist=nameslist|sort(attribute='state',reverse=true)|map(attribute='entity_id')|list%}

This sorts the list, based on the state, returning an array of entity_id’s

Sorry to revive this thread, but I hope it may help someone

1 Like

Guys This is the only thread I found on sorting and selecting. I try to build a script which switches of consumers sorted on electricity consumption to stay below a certain threshold. But I cant get it to work yet. The idea is like this but I can’t get the coding right:

alias: Power Off
sequence:
  - service: variable.set_variable
    data:
      variable: power_consumers
      value:
        - entity_id: switch.sonoff_1000bee815
          consumption: "{{ states('sensor.kw_pool_pump') | float }}"
        - entity_id: switch.sonoff_1000fe1730
          consumption: "{{ states('sensor.sonoff_1000fe1730_power') | float }}"
        - entity_id: switch.sonoff_1000a012cb
          consumption: "{{ states('sensor.kw_ventilator_game_room') | float }}"
  - service: variable.sort
    data:
      variable: power_consumers
      attribute: consumption
      reverse: true
  - repeat:
      while:
        - condition: template
          value_template: >-
            {{
            states('sensor.smappee_1107002938_local_total_consumption_active_power')
            | float >= (4000 + states('sensor.kw_excess_solar_power') | float *
            1.0) }}
      sequence:
        - service: switch.turn_off
          data:
            entity_id: "{{ power_consumers[loop.index0].entity_id }}"
        - delay: "00:00:05"
        - service: homeassistant.update_entity
          entity_id: sensor.smappee_1107002938_local_total_consumption_active_power
mode: restart
variables:
  power_consumers: []
icon: mdi:transfer-down

The challenge is in the service: variable.set_variable. That is not working but I don’t know what to use or how to use a sorted list.

Any idea what I can use here?

On the basis of your examples I have rework it to:

alias: Power Off
sequence:
  - service: input_text.set_value
    data:
      entity_id: input_text.power_consumers
      value: >-
        {%- set consumers = [
          {'entity_id': 'switch.sonoff_1000bee815', 'consumption': states('sensor.kw_pool_pump') | float }, 
          {'entity_id': 'switch.sonoff_1000fe1730', 'consumption': states('sensor.sonoff_1000fe1730_power') | float },
          {'entity_id': 'switch.sonoff_1000a012cb', 'consumption': states('sensor.kw_ventilator_game_room') | float },
          ] -%}
        {% set consumers = consumers| sort(attribute='consumption',
        reverse=true) | map(attribute='entity_id') | list %}  
  - repeat:
      while:
        - condition: template
          value_template: >-
            {{
            states('sensor.smappee_1107xx2938_local_total_consumption_active_power')
            | float >= (4000 + states('sensor.kw_excess_solar_power') | float *
            1.0) }}
      sequence:
        - service: switch.turn_off
          data:
            entity_id: "{{ consumers[0] }}"
        - delay: "00:00:05"
        - service: homeassistant.update_entity
          entity_id: sensor.smappee_1107xx2938_local_total_consumption_active_power
mode: restart
variables:
  power_consumers: []
icon: mdi:transfer-down

The script runs in terms of coding but I am not sure about the sorting. I still need some serious testing but its closer already…

Clearing the list at the end I still have to correct.

1 Like

At the end it boils down to the following part works perfectly in the developers template tool but I can’t get it to work in the script. Somehow I can’t get the value or state of x assigned to an input text:

{% set x = [
                {'entity_id': 'switch.sonoff_1000bee815', 'consumption': states('sensor.kw_pool_pump') | float }, 
                {'entity_id': 'switch.sonoff_1000fe1730', 'consumption': 
                  states('sensor.sonoff_1000fe1730_power') | float },
                {'entity_id': 'switch.sonoff_1000a012cb', 'consumption': 
                  states('sensor.kw_ventilator_game_room') | float },
                ] %}
              {% set x = x | sort(attribute='consumption', reverse=true) | map(attribute='entity_id') | list %}  
              {% set x = x|first|string %}  

In the development template it gives perfectly the entity_id of the highest consumer (x) of the list but in the script I can’t make it work.

I used a similar solution to you @Ih8rain2 although my use case was a little different. In my case I wanted a list of the top 5 energy consumers in my house which displayed the friendly name of the entity. My solution works as follows:

I have a global macro defined in config/custom_templates/top_consumers.jinja

{% macro top_power_consumers(index) %}
{% set entity_list = [
    {'entity_id': 'sensor.power_1', 'consumption': states('sensor.power_1') | default(0) | float },
    {'entity_id': 'sensor.power_2', 'consumption': states('sensor.power_2') | default(0) | float },
    {'entity_id': 'sensor.power_3', 'consumption': states('sensor.power_3') | default(0) | float },
    {'entity_id': 'sensor.power_4', 'consumption': states('sensor.power_4') | default(0) | float },
    {'entity_id': 'sensor.power_5', 'consumption': states('sensor.power_5') | default(0) | float },
    {'entity_id': 'sensor.power_6', 'consumption': states('sensor.power_6') | default(0) | float },
    {'entity_id': 'sensor.power_7', 'consumption': states('sensor.power_7') | default(0) | float },
    {'entity_id': 'sensor.power_8', 'consumption': states('sensor.power_8') | default(0) | float },
    {'entity_id': 'sensor.power_9', 'consumption': states('sensor.power_9') | default(0) | float }] %}
{% set sorted_list=entity_list | sort(attribute='consumption',reverse=true) | map(attribute='entity_id') | list %}
{{ sorted_list[index] | trim }}
{% endmacro %}

Then I have 5 template sensors defined as follows which just index through the sorted_list (this is just the first sensor):

- sensor:
  - name: >
      {% from 'top_consumers.jinja' import top_power_consumers %}
      {% set name = state_attr(top_power_consumers(0) | trim, 'friendly_name') %}
      {{ name }}
    state: >
      {% from 'top_consumers.jinja' import top_power_consumers %}
      {% set state = states(top_power_consumers(0) | trim) %}
      {{ state }}
    unique_id: sensor.top_power_consumer_first
    unit_of_measurement: W
    state_class: measurement

Then I have an entites card in my custom energy dashboard which list each of the sensors:

type: entities
entities:
  - entity: sensor.top_power_consumer_first
  - entity: sensor.top_power_consumer_second
  - entity: sensor.top_power_consumer_third
  - entity: sensor.top_power_consumer_fourth
  - entity: sensor.top_power_consumer_fifth

I do the same for energy, which seems to work as expected, and the names and state values in the dashboard updated dynamically as devices switch on and off.

I had a couple of issues during implementing. Firstly, I had was the some leading/trailing whitespace in the return value of the macro. Unfortunately the trim at the end of the macro did not work, and I have to use trim in all the places where the macro is called. Perhaps the whitespace is also the cause of your problem and you need to call trim?

Secondly, there is some bug when the template sensors get created where they did not receive the unique_id I defined, and they ended up with some unique_id which was derived from the name. It was enough to find the sensor in the settings->entities list and manually modify the unique_id via the GUI.

Hi,
I’ve got this card on my dashbord that tell me when is the next garbage collection and which kind:

          - type: custom:state-switch
            entity: template
            template: >
              {% set sensors = {
                    'carta': 'sensor.carta',
                    'plastica': 'sensor.plastica_e_lattine',
                    'organico': 'sensor.organico',
                    'indifferenziato': 'sensor.indifferenziato',
                    'verde': 'sensor.verde'
                  } %}
              {% set nearest_sensor = sensors|dictsort|first %}
              {% set entity_id = nearest_sensor[1] %}
              {{ entity_id }}
            states: 
              1: 
                type: 'custom:button-card'
                entity: '{{ entity_id }}'
                name: '{{ entity_id.split(".")[1] }}'
                template:
                  - base
                  - icon_garbage

it suppose to be like this:
image

the state of my sensor.carta:


the output of the template is correct on dev tools, but my card is not displayed
Basically I sort my garbage entities by state, that are the days to come…
any advice?