Danh sách các dicts đến dict đa cấp dựa trên thông tin chuyên sâu


9

Tôi có một số dữ liệu, ít nhiều như thế này:

[
{"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},
]

Tôi muốn biến nó thành một chế độ đa cấp dựa trên mức độ sâu (khóa "cấp độ"):

{
    "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": {}}}}}}
}

Tất cả những gì tôi có thể nghĩ ra ngay bây giờ là đoạn mã nhỏ này ... rõ ràng bị hỏng sau vài mục:

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}

Ban đầu ngồi xuống nó vào thứ Sáu và nó được cho là chỉ là một bài tập nhỏ ....

Câu trả lời:


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)

đầu ra:

{'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': {}}}}}}}

sự hạn chế:

  • level >= 0
  • Bất kỳ levelkhông thể lớn hơn +1mức tối đa xuất hiện trước đó.

giải trình:

  • parents là một từ điển để nhớ yếu tố cuối cùng cho mỗi cấp độ.
  • root là một điểm bắt đầu (yếu tố giả).
  • Hợp lý:
    • Bắt đầu với -1cấp độ chỉ ra root.
    • Tạo một mục và đăng ký nó vào cha mẹ children.
    • Cập nhật cùng mục vào parentstừ điển.
    • Nói lại.
    • Chiết xuất root['children'].

1

Giải pháp khác sử dụng đệ quy (hạn chế tương tự như với câu trả lời của Boseong Choi's):

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))

-1

Bạn có thể sử dụng đệ quy:

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))

Đầu ra:

{
  "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": {}
                }
            }
         }
      }
   }
}

Tại sao các downvote?
Ajax1234
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.