2014-07-20 11 views
5

mam AF Lista tej struktury przekazany do szablonu z nazwą bars w Pythonie 3.4:Jinja pętla na zagnieżdżone listy tworzy pusty wyjście

[{'var': 1.18, 'occurrences': [0.0805, 0.0808, 0.0991, 0.0994, 0.2356], 'name': 'item name'}, 
{'var': 2.31, 'occurrences': [1.0859, 1.1121, 1.4826, 1.4829, 1.8126, 1.8791], 'name': 'other name'}] 

chcę tworzyć następujące dane wyjściowe dla każdego słownika:

% List with names 
item 1: item name 
item 2: other name 

% List with vars 
item 1: 1.18 
item 2: 2.31 

% List with occurences 
item 1: 0.0805, 0.0808, 0.0991, 0.0994, 0.2356 
item 2: 1.0859, 1.1121, 1.4826, 1.4829, 1.8126, 1.8791 

Pierwsze dwa nie stanowią problemu, ale nie mogę go włączyć do zapętlenia listy wystąpień. Używam następujący jinja szablonu:

{% for item in bars %} 
    item {{ loop.index }}: {{ item.name }} 
{% endfor %} 

{% for item in bars %} 
    item {{ loop.index }}: {{ item.var }} 
{% endfor %} 

{% for item in bars recursive %} 
    {% if item.occurrences %} 
    Item {{ loop.index}}: {{ loop(item.occurrences) }} 
    {% else %} 
    No content 
    {% endif %} 
{% endfor %} 

To daje ten dziwny wyjście w trzecim przypadku:

Item 1:  No content 
No content 
No content 
No content 
No content 

Item 2:  No content 
No content 
No content 
No content 
No content 
No content 

To jest dziwne, ponieważ wydaje się, że pętle każdy element listy z wystąpień, ale nie zdaje testu treści. Co ja robię źle?

Edytuj: Wszystkie trzy odpowiedzi wskazywały na mnie we właściwym kierunku, ale @famousgarkin daje najbardziej wyszukaną i elastyczną odpowiedź. Skończyło się następujące rozwiązanie:

{% for item in bars %} 
    Item {{ loop.index }}: {% for occurrence in item.occurrences %} subitem {{ loop.index }}: {{ occurrence }} {% endfor %} 
{% endfor %} 

To pozwala mi ująć każdy element w osobnym kontekście, który jest to, co chcę. Ale ponieważ cel ten nie był jasny od samego początku, chciałbym móc przegłosować wszystkie twoje odpowiedzi. Przepraszamy, ale dziękuję wszystkim za szybką pomoc!

Odpowiedz

3

Jeśli nie chcesz formatować zagnieżdżonych elementów przy użyciu tej samej logiki, nie używaj rekursji.

W twojej próbce, zapętlając elementy bars, przechodzi do właściwej ścieżki, ponieważ na wyjściu widać Item n:. Następnie przechodzi do wywołania rekursywnego w celu przetworzenia elementów item.occurrences. Teraz, gdy zapyta, czy istnieje occurrences, to faktycznie pyta o numer bar.occurrences[i].occurrences[j], który oczywiście nie ma atrybutu occurrences i przechodzi do ścieżki .Można zobaczyć go w akcji przy użyciu następujących:

{% for item in bars recursive %} 
    {% if item.occurrences %} 
    Item {{ loop.index }}: {{ loop(item.occurrences) }} 
    {% else %} 
    No content, {{ item.__class__ }}, {{ item }} 
    {% endif %} 
{% endfor %} 

Wynik:

Item 1: No content, <type 'float'>, 0.0805 
No content, <type 'float'>, 0.0808 
No content, <type 'float'>, 0.0991 
No content, <type 'float'>, 0.0994 
No content, <type 'float'>, 0.2356 
... 

będzie działać tak, na przykład:

{% for item in bars %} 
    {% if item.occurrences %} 
    Item {{ loop.index }}: {{ item.occurrences }} 
    {% else %} 
    No content 
    {% endif %} 
{% endfor %} 

Wynik:

Item 1: [0.0805, 0.0808, 0.0991, 0.0994, 0.2356] 
Item 2: [1.0859, 1.1121, 1.4826, 1.4829, 1.8126, 1.8791] 

Jeśli chcesz powtórzyć rzeczy samodzielnie zapewnić własne formatowanie, można na przykład użyć Jinja join filtr:

{% for item in bars %} 
    {% if item.occurrences %} 
    Item {{ loop.index }}: {{ item.occurrences|join(', ') }} 
    {% else %} 
    No content 
    {% endif %} 
{% endfor %} 

Wynik:

Item 1: 0.0805, 0.0808, 0.0991, 0.0994, 0.2356 
Item 2: 1.0859, 1.1121, 1.4826, 1.4829, 1.8126, 1.8791 

lub pętlę ponownie potoczyć zupełnie niestandardowego formatowania:

{% for item in bars %} 
    {% if item.occurrences %} 
    Item {{ loop.index }}: 
    {% for occurrence in item.occurrences %} 
     {{ loop.index }}. {{ occurrence }} 
    {% endfor %} 
    {% else %} 
    No content 
    {% endif %} 
{% endfor %} 

Wynik:

Item 1: 
1. 0.0805 
2. 0.0808 
3. 0.0991 
4. 0.0994 
5. 0.2356 
... 
0

Wystarczy wydrukować listę.

{% for item in bars %} #recursive not needed 
    {% if item.occurrences %} 
    Item {{ loop.index }}: {{ item.occurrences }} #we're not looping here, just printing out the list 
    {% endif %} 
{% endfor %} 

Jeśli bars zawsze będzie occurrences, nie będzie nawet potrzeby sprawdzania if.

Aby wydrukować indvidual elementy z wystąpień prostu iteracyjne nad nim,

Item {{ loop.index}}: {% for occurrence in occurrences %} 
         {{ occurrence }}{% if not loop.last %}, {% endif %} 
         {% endfor %} 

Jeśli zamierzasz wydrukować całą listę tak, można po prostu użyć filtru, która zwraca reprezentację str listy bez nawiasy kwadratowe.

+0

Ale co mam zrobić, aby zapętlić listę i wydrukować każdy element zamiast drukowania całej listy? Nawiasem mówiąc, źle zrozumiałem instrukcję if, zamierzając sprawić, by sprawdzono, czy wystąpienia były prawdziwe, ale teraz widzę, że to było złe. Nie potrzebuję tego. @vikki – Stenskjaer

+0

@Stenskjaer, ponieważ 'occurrences' jest listą, możesz po prostu powtórzyć ją ponownie, zobacz moją edycję. – vikki

0

Oto działający kod.

  • zarządzania spacji aby utrzymać linie jak planowano
  • stosując filtr join do listy zdarzeń
  • usuniętymi recursive z zapętlenie nad zdarzeniami (ponieważ dane są płaskie i nie zagnieżdżone)

tworzyć Uruchamianie tego skryptu:

from jinja2 import Template 

bars = [{'var': 1.18, 'occurrences': [0.0805, 0.0808, 0.0991, 0.0994, 0.2356], 'name': 'item name'}, 
    {'var': 2.31, 'occurrences': [1.0859, 1.1121, 1.4826, 1.4829, 1.8126, 1.8791], 'name': 'other name'}] 
templ_str = """ 
% List with names 
{% for item in bars -%} 
    item {{ loop.index }}: {{ item.name }} 
{% endfor %} 
% List with vars 
{% for item in bars -%} 
    item {{ loop.index }}: {{ item.var }} 
{% endfor %} 
% List with occurrences 
{%- for item in bars %} 
item {{ loop.index}}:{{" "}} 
    {%- if item.occurrences -%} 
     {{ item.occurrences|join(", ") }} 
    {%- else -%} 
    No content 
    {%- endif -%} 
{%- endfor -%} 
""" 
templ = Template(templ_str) 
print templ.render(bars=bars) 

Będziesz ge t ten wynik:

% List with names 
item 1: item name 
item 2: other name 

% List with vars 
item 1: 1.18 
item 2: 2.31 

% List with occurrences 
item 1: 0.0805, 0.0808, 0.0991, 0.0994, 0.2356 
item 2: 1.0859, 1.1121, 1.4826, 1.4829, 1.8126, 1.8791