如何仅通过Jinja模板移除数组对象中重复name属性的条目?
问题描述
我有一个名为data的对象数组,原始数据如下:
{"data": [ { "name": "Erich", "fruit": "apple" }, { "name": "Fred", "fruit": "orange" }, { "name": "Erich", "fruit": "grape" }, { "name": "Fred", "fruit": "banana" } ]}
希望仅用Jinja模板移除name键值重复的对象,得到如下结果(不关心保留哪一个重复对象):
{"data": [ { "name": "Erich", "fruit": "apple" }, { "name": "Fred", "fruit": "orange" } ]}
同时想了解如何通过其他键值对的逻辑来决定保留哪个对象。
解决方案
1. 不关心保留顺序,仅按name去重
利用Jinja的临时集合跟踪已出现的name,遍历数组时只保留首次出现的对象:
{% set seen_names = [] %} {"data": [ {% for item in data %} {% if item.name not in seen_names %} {% do seen_names.append(item.name) %} {{ item | tojson }}{% if not loop.last %},{% endif %} {% endif %} {% endfor %} ]}
原理:用seen_names记录已经处理过的name,首次遇到某个name时保留对应对象并将name加入集合,后续重复项直接跳过,最终输出符合要求的去重结果。
2. 按其他键值逻辑决定保留对象
可以先对数组按指定规则排序,再执行去重操作,这样排序后的首个对象会被保留。
示例1:保留fruit字母排序最靠前的对象
通过sort过滤器按fruit字段字母顺序排序,再去重:
{% set sorted_data = data | sort(attribute='fruit') %} {% set seen_names = [] %} {"data": [ {% for item in sorted_data %} {% if item.name not in seen_names %} {% do seen_names.append(item.name) %} {{ item | tojson }}{% if not loop.last %},{% endif %} {% endif %} {% endfor %} ]}
处理后,Erich会保留apple(字母顺序早于grape),Fred会保留banana(字母顺序早于orange)。
示例2:自定义fruit优先级规则
先定义fruit的优先级映射,再按权重排序后去重:
{% set fruit_priority = {'apple': 1, 'orange': 2, 'grape': 3, 'banana': 4} %} {% set sorted_data = data | sort(key=lambda x: fruit_priority.get(x.fruit, 99)) %} {% set seen_names = [] %} {"data": [ {% for item in sorted_data %} {% if item.name not in seen_names %} {% do seen_names.append(item.name) %} {{ item | tojson }}{% if not loop.last %},{% endif %} {% endif %} {% endfor %} ]}
这里通过fruit_priority给不同水果赋值权重,权重越小优先级越高,排序后优先保留权重小的对象。
内容的提问来源于stack exchange,提问作者Erich Wehrmann
相关产品推荐
相关产品推荐

