Unique Filter of List in Jinja2

Viewed 21026

I have the following YAML structure:

bri:
  cards:
    - slot: "1"
      subslot: "0"
      ports: 2
    - slot: "1"
      subslot: "1"
      ports: 2
    - slot: "1"
      subslot: "2"
      ports: 2
    - slot: "2"
      subslot: "0"
      ports: 2
    - slot: "2"
      subslot: "1"
      ports: 2

I am attempting to use Jinja2 to get a unique list of slots, i.e.:

['1', '2']

So far, I've managed to apply the following:

{{ bri.cards|map(attribute='slot')|list }}

Which gives me:

['1', '1', '1', '2', '2']

However, I don't seem to be able to find a way to get a unique list.

Ansible

Ansible appears to have a "unique" filter that can do this. But I'm not using Ansible in this case.

My question

Can anyone suggest the best way to achieve this? Should (or can) this be done natively with Jinja2, or should I adopt an alternative approach?

4 Answers

Since jinja2 2.10

A unique filter was added in version 2.10 (released 2017-11-08). You can check the change log and the PR.

Usage example

from jinja2 import Template


template = Template("""
  {% for x in a|unique %}
    <li>{{ x }}</li>
  {% endfor %}
""")

r = template.render(a=[1, 2, 3, 4, 1, 5, 4])

print(r)

Output:

<li>1</li>

<li>2</li>

<li>3</li>

<li>4</li>

<li>5</li>

Similar to above by doru with the append functions, but I noticed Ansible doesn't load the 'do' module for Jinja2, working around that is possible as such: {{ bucket.append(client.client_id) }}

{% set slots = [] %}
{% for slot in bri.cards if slot not in slots %}
    {{ slots.append(slot) }}
{% endfor %}

So using {{}} syntax, you can still issue the append function call, and not have Ansible throw Jinja syntax errors.

Related