1

I've been using Jinja and DBT for a month now, and despite reading a lot about it, I didn't quite figure out how to create a list from another, using a simple for loop like I would in Python. Just a toy example:

{%- set not_wanted_columns = ['apple', 'banana'] -%} 
{%- set all_columns = ['kiwi', 'peach', 'apple', 'banana', 'apricot', 'pineapple'] -%}

What I want is a list as so:

{% set filtered_columns = ['kiwi', 'peach', 'apricot', 'pineapple'] %}

Naturally, I don't want to manually write this result because the full list might be dynamic or too long. I'm not even sure if Jinja does actually support this, although I do think this is a common problem.

β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
Tamir
  • 13
  • 3

1 Answers1

0

As you have probably read from the documentation:

Please note that assignments in loops will be cleared at the end of the iteration and cannot outlive the loop scope. Older versions of Jinja had a bug where in some circumstances it appeared that assignments would work. This is not supported.

Source: https://jinja.palletsprojects.com/en/3.1.x/templates/#for

And I guess when you are speaking about

using a simple for loop like I would in Python

What you mean here is using a list comprehension.

So, as showed in the documentation, Jinja is using filter to achieve this:

Example usage:

{{ numbers|select("odd") }} 
{{ numbers|select("divisibleby", 3) }} 

Similar to a generator comprehension such as:

(n for n in numbers if test_odd(n))
(n for n in numbers if test_divisibleby(n, 3)) 

Source: https://jinja.palletsprojects.com/en/3.1.x/templates/#jinja-filters.select

There are actual four of those filter acting as generator comprehension:


So, in your case, a reject filter would totally do the trick:

{%- set filtered_columns = all_columns
     | reject('in', not_wanted_columns) 
     | list 
-%}

But, if you really want, you could also achieve it in a for:

{%- for column in all_columns if column not in not_wanted_columns -%}
  {% do filtered_columns.append(column) %}
{%- endfor -%}

The do statement being a way to use list.append() without oddities being printed out: https://jinja.palletsprojects.com/en/3.1.x/templates/#expression-statement.

β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
  • Nice! I had just experimented with the reject and made something akin to it, however, I don't quite understand the reason for the last pipe for list, given that we already start with a list. – Tamir Aug 08 '22 at 09:36
  • In some versions of Jinja the filter like `select`, `reject`, `map`, make you end up with a generator object, and you have to cast it back as a list. You do not have to do it in recent version anymore, though. – β.εηοιτ.βε Aug 08 '22 at 09:51