在Jinja中分组排序列表

时间:2013-07-13 05:45:11

标签: group-by jinja2

似乎你不能在不丢失排序顺序的情况下对jinja中的排序列表进行分组。

这是一个示例模板:

{% set l = [{'c': 3, 'result': 1.0},
            {'c': 3, 'result': 2.0},
            {'c': 9, 'result': 3.0},
            {'c': 1, 'result': 4.0}] %}
{% for d in l|groupby('c') %}
    {{d}}
{% endfor %}

不幸的是,这个模板输出:

(1, [{'c': 1, 'result': 4.0}])
(3, [{'c': 3, 'result': 1.0}, {'c': 3, 'result': 2.0}])
(9, [{'c': 9, 'result': 3.0}])

但我期待的是:

(3, [{'c': 3, 'result': 1.0}, {'c': 3, 'result': 2.0}])
(9, [{'c': 9, 'result': 3.0}])
(1, [{'c': 1, 'result': 4.0}])

我绝对要按照预先排序的顺序保留这些项目。

有人知道如何实现这个目标吗?

3 个答案:

答案 0 :(得分:1)

更新到最新的jinja版本:

import jinja2

from jinja2 import environmentfilter
from itertools import groupby
from jinja2.filters import make_attrgetter, _GroupTuple

@environmentfilter
def do_sorted_groupby(environment, value, attribute):
    expr = make_attrgetter(environment, attribute)
    return [_GroupTuple(key, list(values)) for key, values
            in groupby(value, expr)]

env = jinja2.Environment()
env.filters['sorted_groupby'] = do_sorted_groupby

ret = env.from_string('''
{% set l = [{'c': 3, 'result': 1.0},
            {'c': 3, 'result': 2.0},
            {'c': 9, 'result': 3.0},
            {'c': 1, 'result': 4.0}] %}
{% for d in l|sorted_groupby('c') %}
    {{d}}
{% endfor %}
''').render()

print(ret)

答案 1 :(得分:0)

正如@Blender在评论中指出的那样,jinja使用sorted根据收到的密钥对传递的列表进行排序。

如果您想保留排序顺序,我担心唯一的解决方案是编写自己的jinja过滤器。

这里实现了我实现的过滤器:

from jinja2 import environmentfilter
from itertools import groupby
from jinja2.filters import make_attrgetter, _GroupTuple
@environmentfilter
def do_groupby(environment, value, attribute):
    expr = make_attrgetter(environment, attribute)
    return map(_GroupTuple, groupby(value, expr))

注意:此过滤器仅在收到的列表分组时正常工作(组指示符必须按顺序排列)。例如,此列表不会正确分组:

[{'c': 3, 'result': 1.0},
 {'c': 9, 'result': 2.0},
 {'c': 3, 'result': 3.0},
 {'c': 1, 'result': 4.0}]

答案 2 :(得分:0)

希望这个答案能解决您的问题

{% for d in l|groupby('c')|reverse %}
   {{d}}
{% endfor %}