将扁平数据转换为列表字典树

1 投票
1 回答
574 浏览
提问于 2025-04-18 07:09

在我的项目中,我需要列出所有产品,并将它们以嵌套的JSON格式发送到我的应用程序。我已经写了代码来实现这个功能,但我不太明白我的逻辑哪里出错了。以下是我的代码。

我手头的数据是一些简单的字段,比如 typecategorysubnameprice 等等。

因为 Type、Cat、Sub 是放在一个字符串里的,所以我用 re.search 来解析它们,结果存储在 parse 里。

在我的 Python main 函数中,我获取所有记录,然后在 for each row in rows 循环中,我调用:

    product_list = add_on_tree(parse, product_list, p_dict, 1)

这里的 product_list 一开始是 [],p_dict 是一个字典,像这样:{name:'', price:'',... 等等}

def add_on_tree(parse, plist, pdict, i):
    if parse.group(i):
        listCheck = ""
        """
        empty   ==>> plist is empty
        match   ==>> plist[i].type =  parse.group(i)
        nomatch ==>> plist[i].type != parse.group(i)
        """
        if plist==[]:
            listCheck = "empty"
        else:
            listCheck = "nomatch"
            for l in plist:
                if l["type"]==parse.group(i):
                    listCheck = "match"

        if listCheck in ["empty", "nomatch"]:
            newdict = {}
            newdict["type"] = parse.group(i)
            newdict["sub"] = []
            newdict["leaves"] = []
            try:
                if parse.group(i+1):
                    sublist = add_on_tree(parse, [], pdict, i+1 )
                    newdict["sub"] = sublist
                    plist.append(newdict)
                    return plist
            except:
                newdict["leaves"].append(pdict)
                plist.append(newdict)
                return plist
        else:
            for p in plist:
                if p["type"]==parse.group(i):
                    try:
                        if parse.group(i+1):
                            sublist = add_on_tree(parse, p["sub"], pdict, i+1)
                            p["sub"] = sublist
                            return plist
                    except:
                        p["leaves"].append(pdict)
                        return plist
                else:
                    p["sub"] = ["Error Somewhere", p["type"]]
                    return plist

需要的树形结构

 [
   {
     type     : 'car entertainment',
     sub      : [
                  {
                    type     : 'Head Unit',
                    sub      : [
                                 {
                                   type     : 'USB',
                                   sub      : [],
                                   products : [
                                                {
                                                  name : '',
                                                  url  : '',
                                                  price: ''
                                                }
                                              ]
                                 }
                               ],
                    products : []
                  },
                  {},
                  {}
                ],
     products : []
   },
   {
     type     : 'home entertainment',
     sub      : [
                  {
                    type     : 'Audio',
                    sub      : [],
                    products : [
                                 {
                                   name:,
                                   url:,
                                   type:
                                 },
                                 {
                                   name:,
                                   url:,
                                   type:
                                 }
                               ]
                  },
                  {},
                  {}
                ],
     products : []
   }
 ]

我得到的结果:

{
  "products": [
    {
      "leaves": [], 
      "sub": [
        "Error Somewhere", 
        "Car Entertainment"
      ], 
      "type": "Car Entertainment"
    }, 
    {
      "leaves": [], 
      "sub": [
        {
          "leaves": [], 
          "sub": [
            {
              "leaves": [
                {
                  "desc": "", 
                  "image": "", 
                  "name": "", 
                  "price": 25000.0, 
                  "url": ""
                }
              ], 
              "sub": [], 
              "type": "Smartest"
            }
          ], 
          "type": "Smart"
        }
      ], 
      "type": "Home Entertainment"
    }
  ]
}

flask 中,我使用 jsonify(products=product_list),这表示最外层的字典 products

附加信息

  1. 我使用的是 mysql 数据库,里面只有四条记录。
  2. 当我使用 pdb 调试时,我发现当出现 'error somewhere' 的时候,打印 p["type"] 返回的是 p['type']。
  3. 如果我把

    product_list = add_on_tree(parse, product_list, p_dict, 1)
    

    改成

    product_list = add_on_tree(parse, [], p_dict, 1)
    

    最后一行就能正确渲染。这让我觉得我的逻辑在列表为空的时候是没问题的,但在需要插入到已有结构时就出错了。

任何帮助都非常感谢。提前谢谢你们!

更新 - 解决方案

正如 @matt 指出的那样,错误出在:

                else:
                    p["sub"] = ["Error Somewhere", p["type"]]
                    return plist

以下的修改解决了这个错误:

                else:
                    return plist

PS - 我后来把嵌套结构替换成了简单数据。嵌套(处理)应该留给最终的应用程序来做。否则会带来更多麻烦,而不是解决问题。

1 个回答

1

你的函数有点复杂,不过我觉得我看到了直接的问题:

else:
    p["sub"] = ["Error Somewhere", p["type"]]
    return plist

如果列表中的第一个项目和你要找的类型不匹配,你就会出错。其实你应该是在遍历整个列表后,如果没有找到你想要的类型再出错。

试着把错误检查放在循环之后。

撰写回答