รายชื่อ dicts เพื่อหลายระดับ dict ตามข้อมูลเชิงลึก


9

ฉันมีข้อมูลบางอย่างมากหรือน้อยเช่นนี้

[
{"tag": "A", "level":0},
{"tag": "B", "level":1},
{"tag": "D", "level":2},
{"tag": "F", "level":3},
{"tag": "G", "level":4},
{"tag": "E", "level":2},
{"tag": "H", "level":3},
{"tag": "I", "level":3},
{"tag": "C", "level":1},
{"tag": "J", "level":2},
]

ฉันต้องการเปลี่ยนเป็น dict หลายระดับตามระดับความลึก (ระดับ "คีย์"):

{
    "A": {"level": 0, "children": {
            "B": {"level": 1, "children": {
                    "D": {"level": 2, "children": {
                            "F": {"level": 3, "children": {
                                    "G": {"level": 4, "children": {}}}}}},
                    "E": {"level": 2, "children": {
                            "H": {"level": 3, "children": {}},
                            "I": {"level": 3, "children": {}}}}}},
            "C": {"level": 1, "children": {
                    "J": {"level": 2, "children": {}}}}}}
}

สิ่งที่ฉันสามารถทำได้ในตอนนี้คือรหัสชิ้นเล็ก ๆ ... ซึ่งเห็นได้ชัดหลังจากรายการบางอย่าง:

def list2multilevel(list):
    children = {}
    parent = list.pop(0)
    tag = parent.get("Tag")
    level = parent.get("Level")
    for child in list:
        ctag = child.get("Tag")
        clevel = child.get("Level")
        if clevel == level + 1:
            children.update(list2multilevel(list))
        elif clevel <= level:
            print(clevel, level)
            break
    return {tag: children}

แต่เดิมนั่งลงบนมันในวันศุกร์และมันควรจะเป็นเพียงการออกกำลังกายเล็ก ๆ น้อย ๆ ....

คำตอบ:


6
data = [
    {"tag": "A", "level": 0},
    {"tag": "B", "level": 1},
    {"tag": "D", "level": 2},
    {"tag": "F", "level": 3},
    {"tag": "G", "level": 4},
    {"tag": "E", "level": 2},
    {"tag": "H", "level": 3},
    {"tag": "I", "level": 3},
    {"tag": "C", "level": 1},
    {"tag": "J", "level": 2},
]

root = {'level': -1, 'children': {}}
parents = {-1: root}
for datum in data:
    level = datum['level']
    parents[level] = parents[level - 1]['children'][datum['tag']] = {
        'level': datum['level'],
        'children': {},
    }
result = root['children']
print(result)

เอาท์พุท:

{'A': {'level': 0, 'children': {'B': {'level': 1, 'children': {'D': {'level': 2, 'children': {'F': {'level': 3, 'children': {'G': {'level': 4, 'children': {}}}}}}, 'E': {'level': 2, 'children': {'H': {'level': 3, 'children': {}}, 'I': {'level': 3, 'children': {}}}}}}, 'C': {'level': 1, 'children': {'J': {'level': 2, 'children': {}}}}}}}

ข้อ จำกัด :

  • level >= 0
  • สิ่งใด ๆlevelต้องไม่ใหญ่กว่า+1ระดับสูงสุดที่ปรากฏก่อนหน้านี้

คำอธิบาย:

  • parents เป็นพจนานุกรมที่ต้องจำองค์ประกอบสุดท้ายของแต่ละระดับ
  • root เป็นจุดเริ่มต้น (องค์ประกอบจำลอง)
  • ตรรกะ:
    • เริ่มต้นด้วยระดับที่บ่งชี้ว่า-1root
    • childrenทำให้รายการและลงทะเบียนเข้าของผู้ปกครอง
    • อัปเดตรายการเดียวกันเป็นparentsพจนานุกรม
    • ทำซ้ำ
    • root['children']สารสกัด

1

โซลูชันอื่นที่ใช้การเรียกซ้ำ (ข้อ จำกัด เดียวกับคำตอบของ Boseong Choi):

data = [
    {"tag": "A", "level": 0},
    {"tag": "B", "level": 1},
    {"tag": "D", "level": 2},
    {"tag": "F", "level": 3},
    {"tag": "G", "level": 4},
    {"tag": "E", "level": 2},
    {"tag": "H", "level": 3},
    {"tag": "I", "level": 3},
    {"tag": "C", "level": 1},
    {"tag": "J", "level": 2},
]

def make_node(dic):
    node = dic.copy()
    node["children"] = {}
    tag = node.pop("tag")
    return tag, node

def add_child(parent, child, tag):
    assert child["level"] > parent["level"]
    if child["level"] == parent["level"] + 1:
        parent["children"][tag] = child
        return True
    for node in parent["children"].values():
        if add_child(node, child, tag):
            return True
    return False

def parse(lst):
    assert lst[0]["level"] == 0
    root_tag, root = make_node(lst[0])
    for item in lst[1:]:
        tag, node = make_node(item)
        add_child(root, node, tag)


print(parse(data))

-2

คุณสามารถใช้การสอบถามซ้ำ:

from itertools import groupby as gb
data = [{'tag': 'A', 'level': 0}, {'tag': 'B', 'level': 1}, {'tag': 'D', 'level': 2}, {'tag': 'F', 'level': 3}, {'tag': 'G', 'level': 4}, {'tag': 'E', 'level': 2}, {'tag': 'H', 'level': 3}, {'tag': 'I', 'level': 3}, {'tag': 'C', 'level': 1}, {'tag': 'J', 'level': 2}]
def to_tree(d, s = 0):
  v = [list(b) for _, b in gb(d, key=lambda x:x['level'] == s)]
  if len(v) == 1:
     return {i['tag']:{'level':s, 'children':{}} for i in v[0]}
  return {v[i][0]['tag']:{'level':s, 'children':to_tree(v[i+1], s+1)} for i in range(0, len(v), 2)}

import json
print(json.dumps(to_tree(data), indent=4))

เอาท์พุท:

{
  "A": {
    "level": 0,
    "children": {
        "B": {
            "level": 1,
            "children": {
                "D": {
                    "level": 2,
                    "children": {
                        "F": {
                            "level": 3,
                            "children": {
                                "G": {
                                    "level": 4,
                                    "children": {}
                                }
                            }
                        }
                    }
                },
                "E": {
                    "level": 2,
                    "children": {
                        "H": {
                            "level": 3,
                            "children": {}
                        },
                        "I": {
                            "level": 3,
                            "children": {}
                        }
                    }
                }
            }
        },
        "C": {
            "level": 1,
            "children": {
                "J": {
                    "level": 2,
                    "children": {}
                }
            }
         }
      }
   }
}

ทำไมต้องลงคะแนน?
Ajax1234
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.