在jinja2循环中对字典进行排序

20

我仍在学习jinja2和flask,并且在使用jinja2中的dictsort时遇到了困难。

因此,我将这个字典传递到jinja2模板中:

{'PEDD United': {'id': 37828, 'rank': 12, 'totalpts': 307},'Fc Mbonabushia': {'id': 205633, 'rank': 6, 'totalpts': 356},'FC Slurp': {'id': 933573, 'rank': 11, 'totalpts': 312},'KFC_Overijse': {'id': 38861, 'rank': 5, 'totalpts': 362},'Fc Paris': {'id': 1538051, 'rank': 2, 'totalpts': 396}}
我想创建一个按照键'totalpts'的值进行排序的表格。我尝试了各种方法,但是它在“排序”时不考虑totalpts。
这是我的其中一个代码:
        <table class="table table-bordered">
        {% for team in league %}
            <tr>
                <td>{{team}}</td>
                {% for data in league[team]|dictsort(league[team]['totalpts']) %}
                <td>{{ league[team]['totalpts'] }}</td>
                {% endfor %}
            </tr>
        {% endfor %}
    </table>

但在这种情况下它不会对任何东西进行排序... 只是打印表中的值而没有任何顺序...

有人可以帮我吗?

谢谢

3个回答

19
你目前的做法行不通,因为一旦你使用{% for team in league %},你已经在使用未排序的字典并从中提取键值对。
我认为|dictsort在这种情况下可能无法帮助你,因为你不能按键或值排序,但可以按照'value'(子字典的)'totalpts'值进行排序。
相反,在向模板传递它之前,你应该以以下方式对这个字典进行排序:
>>> from collections import OrderedDict
>>> league={'PEDD United': {'id': 37828, 'rank': 12, 'totalpts': 307},'Fc Mbonabushia': {'id': 205633, 'rank': 6, 'totalpts': 356},'FC Slurp': {'id': 933573, 'rank': 11, 'totalpts': 312},'KFC_Overijse': {'id': 38861, 'rank': 5, 'totalpts': 362},'Fc Paris': {'id': 1538051, 'rank': 2, 'totalpts': 396}}
>>> league = OrderedDict(sorted(league.items(), key= lambda x: x[1]['totalpts'], reverse=True))
>>> print league
OrderedDict([('Fc Paris', {'id': 1538051, 'rank': 2, 'totalpts': 396}), ('KFC_Overijse', {'id': 38861, 'rank': 5, 'totalpts': 362}), ('Fc Mbonabushia', {'id': 205633, 'rank': 6, 'totalpts': 356}), ('FC Slurp', {'id': 933573, 'rank': 11, 'totalpts': 312}), ('PEDD United', {'id': 37828, 'rank': 12, 'totalpts': 307})])
为了对字典进行排序,我们使用.items()将其转换为由(key, value)元组组成的列表。假设x是其中一个元组,则x[1]包含键为'totalpts'的字典。
>>> league.items()[0]
('Fc Paris', {'id': 1538051, 'rank': 2, 'totalpts': 396})  # = x

现在,我们使用x [1] ['totalpts']对元组进行排序,并使用 reverse=True 以降序排列。

字典本身无法排序,它是一种无序数据类型 - 您可以使用 OrderedDict,或者您可以简单地使用元组:

>>> sorted(league.items(), key= lambda x: x[1]['totalpts'], reverse=True)
[('Fc Paris', {'id': 1538051, 'rank': 2, 'totalpts': 396}), ('KFC_Overijse', {'id': 38861, 'rank': 5, 'totalpts': 362}), ('Fc Mbonabushia', {'id': 205633, 'rank': 6, 'totalpts': 356}), ('FC Slurp', {'id': 933573, 'rank': 11, 'totalpts': 312}), ('PEDD United', {'id': 37828, 'rank': 12, 'totalpts': 307})]

感谢您的帮助,您的答案完美地解决了我的问题,并帮助我学习了元组 :) - Syl

17

你可以使用普通的sort过滤器来对字典项目进行排序。

要按键排序,请使用attribute=0

{% for key, value in data.items()|sort(attribute='0') %}
  {{ key }}: {{ value }}
{% endfor %}

使用 attribute=1 进行按值排序

{% for key, value in data.items()|sort(attribute='1') %}
  {{ key }}: {{ value }}
{% endfor %}

按值属性排序时,请使用attribute=1.name

{% for key, value in data.items()|sort(attribute='1.name') %}
  {{ key }}: {{ value }}
{% endfor %}

这个问题中的循环将被翻译为

{% for team_name, team_attrs in league.items()|sort(attribute='1.totalpts') %}
  <td>{{ team_attrs.totalpts }}</td>
{% endfor %}

我在Jinja2文档中找不到任何关于这些神奇的01的提及,但是这个答案最终让我通过uid对Salt中的字典进行排序: {%- for user,attr in users.items() | sort(attribute="1.uid") %} - Timur Bakeyev
1
@TimurBakeyev 这个可以工作,因为排序过滤器应用于data.items(),它返回一对列表。 0是一对中的第一个元素(键),1是第二个元素(实际值)。 - dpr

3
您可以使用 sorted 将其排序为有序列表:
league = sorted(league, key= lambda x: -league[x]['totalpts'])

不起作用。我得到了这个错误。TypeError:字符串索引必须是整数,而不是str。 - Syl
确实它能工作。然而,Anuj的答案更好,因为我可以使用他的方法仍然访问第二个字典。感谢您的帮助! - Syl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接