按值对dict列表进行分组,然后对一些嵌套dict进行分组

2024-09-24 22:20:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我有这样的数据:

plans = [
  {'code':1, 'name':'Station1', 'plan_type':2, 'layer':1, 'hour':1, 'val':23.34}
  {'code':1, 'name':'Station1', 'plan_type':2, 'layer':1, 'hour':2, 'val':33.34}
  {'code':2, 'name':'Station2', 'plan_type':2, 'layer':1, 'hour':1, 'val':23.34}
  {'code':2, 'name':'Station2', 'plan_type':2, 'layer':1, 'hour':1, 'val':23.34}
....
  {'code':2, 'name':'Station2', 'plan_type':2, 'layer':1, 'hour':1, 'val':23.34}
]

它描述了生产计划。我想在Django模板上显示它的是

 { <code>:{'name':<name>,
            <plan_type>:{<hour>:{'layer':<layer>,'val':<val>} ... }
          }
 }

这意味着按代码分组数据,设置组名称,然后按计划类型分组,对于每个计划,使用小时作为键来描述层和层中的值。 我试着理解列表

   a = { plan['code']:{
            'name':plan['name'],
            p['plan_type']:None for p in plans if p['code'] == plan['code']
        } for plan in plans }

这件事不能过去。有语法错误。我可以获取计划类型的代码作为嵌套dict的键,也可以设置“name”值。有defaultdictitertools的解决方案,但我还没有弄清楚如何应用它们。 这是可行的,但不是我想要达到的目标:

   a = { plan['code']:{
            'name':plan['name'],
            'plan':{p['plan_type']:None} for p in plans if p['code'] == plan['code']
        } for plan in plans }


Tags: 数据代码nameinlayerfortypecode
2条回答

如果我正确地假设您只想在模板中生成结果dict:

我想知道这里最好的办法是使用过滤器吗? 这有点复杂,但一旦生成了dict,就可以使用过滤器提取每个级别。 挑战在于过滤器只能接受一个参数,因此您必须对“条目路径”和您以某种方式提取的内容以及链调用进行编码

我涂鸦的内容如下:

在代码的某个地方注册过滤器:

from typing import List, Dict, Any
from django import template

register = template.Library()

...

@register.filter
def extract_and_group(entries: List[Dict[str, Any]], attribute: str) -> Dict[str, List[Dict[str, Any]]:
  grouped = {}
  for entry in entries:
    key = entry[attribute]
    without_key = entry.copy()
    del without_key[key]
    grouped[key] = grouped.get(key, []) + [without_key]
  return grouped

@register.filter
def further_extract(extracted: Dict[str, Any], path: str) -> Dict[str, Any]:
  paths = path.split(".")
  assert "->" in paths[-1]
  last, key = paths[-1].split("->")
  paths[-1] = last
  dicts = [extracted]
  for p in paths:
    parent_dict = dicts[-1]
    dicts.append(parent_dict[p])

  to_alter = dicts[-2]
  assert isinstance(to_alter, list)
  extracted_entry = extract_and_group(to_alter, key)
  dicts[-2][last] = extracted_entry

  return extracted

您可以通过以下方式在模板中使用它:

plans|extract_and_group:"code"|further_extract:"name"|further_extract:"name->plan_type"|further_extract:"name.plan_type->hour"

为了可读性,我在这里使用了类型提示,但是如果您不在Python3.8+上,可以删除。 无论如何,我还没有测试过这个,它有点难看,但我想这是一个选择?🤔

当然,您不必在模板中执行此操作,因此如果我的假设不正确,您可以调整上述代码,使其不在过滤器中

希望这是一个起点

谢谢,伙计们!我想出来了:

    #making a dict with production plans
    a = {plan['code']:{
            pt['plan_type']:{
                p['hour']:{
                    'layer':p['layer'],'val':p['val']
                } for p in plans if p['code'] == pt['code'] and p['plan_type'] == pt['plan_type']
            } for pt in plans if plan['code'] == pt['code']
        } for plan in plans}

    #making separate dict for names
    names = {plan['code']:plan['name'] for plan in plans}

    #'merging' those dicts
    for tt in a:
        a[tt]['name'] = names[tt]

接吻原则

相关问题 更多 >