tera icon indicating copy to clipboard operation
tera copied to clipboard

Iterating through map in reverse

Open dbrgn opened this issue 5 years ago • 3 comments

Since data is serialized to JSON using serde-json, when iterating over a map the implementation of the map defines the iteration order. serde-json uses a BTreeMap by default, where entries are sorted by key. This means that when iterating over a map using a for loop, the order is always by key.

It would be nice if a map could also be iterated in reverse. The reverse filter only supports arrays and strings though. I tried adding that functionality to the reverse filter (since that seems very natural to me from a user perspective), but since the filter simply returns a new map, that doesn't work (because it always becomes a BTreeMap in the end, which is sorted by key).

We could make serde-json use an insertion-order map by passing in the preserve_order feature, but I'm not sure if that's desired (and it might have undesired side effects).

In case reverse is the wrong place: Jinja provides a dictsort filter, but that would also require the preserve_order feature.

The third option would be to add a special syntax to the for loop, for example something like this:

{% for rev key, value in mymap %}
...

This would call .rev() on the iterator. However, I'm not sure if you want new syntax if filters could in theory achieve the same (with more flexibility, like custom sorting).

dbrgn avatar Jun 11 '20 21:06 dbrgn

I don't think it makes sense in Tera though. Structs are represented as JSON objects, what does it mean to iterate on a dict in reverse in that case? By insertion order like you mentioned? Arrays/strings have some clear meaning for iteration in reverse, dict not so much.

Keats avatar Jun 12 '20 06:06 Keats

The thing is that there still is a clearly defined iteration order:

  • Without preserve_order feature, the entries are iterated sorted alphanumerically by key
  • With preserve_order feature, the entries are iterated sorted by insertion order (which probably means that serde will preserve the order of the original map)

I use BTreeMaps in my code precisely because I want to iterate sorted by key. Just because it gets converted to a JSON object doesn't mean that the order must be undefined. And if it's defined, it could be reversed :slightly_smiling_face:

dbrgn avatar Jun 12 '20 10:06 dbrgn

I guess it should only be implemented if preserve_order is enabled then.

Keats avatar Jun 12 '20 12:06 Keats