Jinja: average of first n items of list

How do I calculate the average of the four highest values of a list of floats (and nils)? In Ruby this would be written as:

list_of_values = [8,1,7,2,6,3,5,4,nil]
top_items = list_of_values.compact.sort.last(4)
top_items.sum / top_items.length.to_f

=> 6.5

…but I’m not yet familiar with Jinja, I’m failing at a few things, e.g. it seems I cannot do something like `

{{ list_of_values | sort(reverse=True) | [:4] }}

…and also I’ve not found the Jinja equivalent to #compact that removes nils from an array/list.

Oh, if anyone can point me to something like “A beginners guide to Jinja for people who know Ruby” I’d appreciate it. Also if there’s a better place to ask for Jinja advice than here in the “Configuration” forum of HA.

Thanks!

There are a number a filters that can be used if you know there will be non-numeric values in the list.

{{(list_of_values | select('is_number') | sort(reverse=True))[:4] | average}}

The is_number filter above can be used to select only the usable values, but the average will fail if there are numeric strings in the list.

A better option for that case would be to cast the values to float or int with defaults using map().

{{(list_of_values | map('float', 0) | sort(reverse=True))[:4] | average}}
2 Likes
{{ (list_of_values | reject('eq', none) | sort(reverse=True))[:4] }}

Reference

Jinja2 reject filter


Not specifically for Ruby users but the official documentation is a good starting point:

Home Assistant implements some, but not all, of Jinja2 (plus some custom additions). Its documentation is here:

https://jinja.palletsprojects.com/en/3.1.x/templates/

The Built-in Filters and Built-in Tests sections are particularly handy.

1 Like

Best to combine them, first only select the numeric values, then map them to float. Otherwise the non-numeric values will be treated as 0.

Unless you want null to be treated as 0, which would make sense. It will become more complicated then if there are other non numeric values like unavailable

Thanks, @123, @Didgeridrew and @TheFes. I don’t want to map the values to a default value, so I’ll use select('is_number') or reject('eq', none). They are temperature values from various indoor sensors, I’m calculating the offset between target temperature and current temperature to see how much heating power is currently needed.

As for Jinja, I’ve seen the documentation. It’s just hard to find something if you don’t know how it is called in a specific language, e.g. the [:4]. I think I’ve seen a website comparing many coding languages with many different examples, hopefully I can find it again and it includes Jinja, that would allow me to compare Ruby code and Jinja next to each other.

Keep in mind that Jinja is a templating language employing python syntax. So that’s where the slicing notation [:4] comes from.

1 Like