首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将树转换为列表

将树转换为列表
EN

Stack Overflow用户
提问于 2014-10-27 20:00:43
回答 3查看 2.7K关注 0票数 0

我有一个树结构,类似于:公司->部门-> ->

我有一个像这样的三重循环结构:

代码语言:javascript
复制
for company in self.Companies():
    cName = company.Name()
    for dept in company.Departments():
        dName = department.Name()
        for role in dept.Roles():
            rName = role.Name()
            roleID = role.ID()

.Name()函数返回一个与Android类似的部门名称。公司可以设置零个或多个部门。

到目前为止,以上都是我所拥有的。我正在尝试开发这个项目,这样我就可以得到一个列表:理想情况下,这是我想要的。如果有重复,列表中的下一项应该保留为空白。或者它可能没有字段,在这种情况下,它也是空白的。

[ “‘Google”,“Android-Sales”,“Marketer”,“A 123”, “Google-Play”,“Developer”,“A 435”, “”,“”,“Tester”,“A 125”, “,”A 126“, “我的小公司”、“”、“超级角色”、“A123”]

否则这也会奏效..。

[ “‘Google”,“Android-Sales”,“Marketer”,“A 123”, “Google”,“Google-Play”,“Developer”,“A 435”, “Google”,“Google-Play”,“Tester”,“A 125”, “Google”,“Google-Play”,“Tester”,“A 126”, “我的小公司”、“超级角色”、“A123”(这里“我的小公司”没有“部门”)。]

每个内部列表的长度应该是4。

EN

回答 3

Stack Overflow用户

发布于 2014-10-27 20:25:03

试着做这样的事情:

代码语言:javascript
复制
tree = {"Google":{"Android":"yes", "Nexus":"no"}}
list_of_lists = []

def listbuilder(sub_tree, current_list):
    for key in sub_tree:
        if isinstance(sub_tree[key], dict):
            listbuilder(sub_tree[key], current_list + [key])
        else:
            list_of_lists.append(current_list + [key] + [sub_tree[key]])

listbuilder(tree,[])

print str(list_of_lists)

输出:

代码语言:javascript
复制
[['Google', 'Nexus', 'no'], ['Google', 'Android', 'yes']]
票数 3
EN

Stack Overflow用户

发布于 2021-09-14 14:50:16

不久前,我需要以结构化的方式将JSON文件插入数据库。基于@Gillespie描述的解决方案,我能够将文件层次结构转换为列表列表。

下面的脚本希望读取一个JSON文件,该文件的项目列表最初由父键"value“标识。下面是data.json文件的一个简单示例。

JSON文件

代码语言:javascript
复制
{
    "value":
    [
        {
            "A": 0,
            "B": 1,
            "C": 2
        },
        {
            "C": {
                "E": 3,
                "F": 4
            },
            "D": [
                {
                    "G": 5
                },
                {
                    "H": 6
                }
            ]
        }
    ]
}

下面的脚本读取一个JSON文件并将其转换为要插入数据库的元组列表。在创建数据库中的表和列之前,请记住删除特殊字符。

Python脚本

代码语言:javascript
复制
import json


def dict_to_list(sub_tree: dict, current_list: [str], items_list: [[str]]) -> [[str]]:   
    try:  # Tree branches.
        for key in sub_tree:
            if isinstance(sub_tree[key], list):
                for sub_item in sub_tree[key]:
                    dict_to_list(sub_tree=sub_item, current_list=current_list + [key], items_list=items_list)
            elif isinstance(sub_tree[key], dict):
                dict_to_list(sub_tree=sub_tree[key], current_list=current_list + [key], items_list=items_list)
            else:
                items_list.append(current_list + [key] + [sub_tree[key]])
    except:  # Tree leaf.
        items_list.append(current_list + [str(sub_tree)])
            
    return items_list
  
  
def json_data_to_samples_list(json_data: dict, data_key: str = 'value', column_sep: str = "_") -> [[(str, str)]]:
    samples_list = []
    
    for parent in json_data[data_key]:
        column_value_tuples = []
        
        for child in dict_to_list(sub_tree=parent, current_list=[], items_list=[]):
            column = column_sep.join(child[:-1])
            value = child[-1]
            column_value_tuples.append((column, value))

        samples_list.append(column_value_tuples)
  
    return samples_list



def main() -> None:
    json_file_path = "data.json"

    with open(json_file_path, mode="r", encoding="utf-8") as file:
        json_data = json.load(file)

    samples_list = json_data_to_samples_list(json_data=json_data)

    print(f"\nExtracted {len(samples_list)} items from the JSON file:")

    for idx, parent in enumerate(samples_list):
        print(f"\n>>>>> Child #{idx}:")

        for child in parent:
            print(f"\t\t{child}")

    print()


if __name__ == '__main__':
    main()

预期产出

代码语言:javascript
复制
Extracted 2 items from the JSON file:

>>>>> Child #0:
                ('A', 0)
                ('B', 1)
                ('C', 2)

>>>>> Child #1:
                ('C_E', 3)
                ('C_F', 4)
                ('D_G', 5)
                ('D_H', 6)
票数 0
EN

Stack Overflow用户

发布于 2022-01-20 19:02:50

除了我的previous answer之外,您还可能希望将一个JSON文件转换为可以插入到数据库中的元组。在这种情况下,您可以使用以下方法。

在运行以下脚本之前,Dict必须导入在 this post中定义的类(只需复制和粘贴它)。这个类对于我们在JSON中序列化对象的方法是基本的。

Python脚本

JSON类的定义。

代码语言:javascript
复制
from __future__ import annotations

from collections import OrderedDict
import logging


logging.basicConfig(level="DEBUG")
LOGGER = logging.getLogger(__name__)


class JSON:
    def __init__(self, dict_list: [dict], key_sep: str = "_", dump_objects: bool = False):
        """
        Instantiates a JSON processing object.

        Parameters
        ----------
        dict_list: [dict]
            List of dictionaries.
        key_sep: str
            Nested keys separator.
        dump_objects: bool
            Whether to dump objects.

        References
        ----------
        [1] 'JSON' class: https://stackoverflow.com/a/70791993/16109419
        [2] 'Dict' class: https://stackoverflow.com/a/70908985/16109419
        """
        self.key_sep = key_sep
        self.dump_objects = dump_objects

        # Serializing dictionaries before processing them:
        self.dict_list = [self.serialize(data=d, dump_objects=dump_objects) for d in dict_list]

    @staticmethod
    def serialize(data: dict, dump_objects: bool = False) -> [dict]:
        """
        Serializes the objects contained in the dictionary.

        Parameters
        ----------
        data: dict
            Dictionary.
        dump_objects: bool
            Whether to dump objects.

        Returns
        -------
        data: dict
            Dictionary.

        Notes
        -----
        This method is required to handle data types not supported by the JSON standard.
        For instance, only native data types are supported in Python (e.g., str, int).
        Custom objects values are dumped into the dictionaries structure.
        """
        serialized_d = Dict(data=data)

        for keys, value in serialized_d.items():
            parsed, parsed_value = False, None

            if hasattr(value, 'isoformat'):  # Date/Datetime object.
                parsed = True
                parsed_value = value.isoformat() if dump_objects else value
            elif hasattr(value, '__dict__'):  # Custom object.
                parsed = True
                value_vars = vars(value)
                value_vars_str = str(value_vars)
                value_str = str(value)

                if value_vars_str == value_str:  # Dict-based object.
                    parsed_value = JSON.serialize(data=value_vars, dump_objects=dump_objects)
                else:  # Not dict-based object.
                    if dump_objects:
                        parsed_value = JSON.serialize(data=value_vars, dump_objects=dump_objects)
                    else:
                        parsed_value = value_str

            if parsed:
                serialized_d.set(keys=keys, value=parsed_value)

        data = serialized_d.data

        return data

    def dict_to_list(
        self,
        sub_tree: dict,
        current_list: [str],
        items_list: [[object]]
    ) -> [[object]]:
        """
        Convert dictionary to items list.

        Parameters
        ----------
        sub_tree
        current_list
        items_list

        Returns
        -------
        items_list: [[object]]
            List of items list.
        """
        try:  # Tree branches.
            for key in sub_tree:
                if isinstance(sub_tree[key], (list, tuple)):
                    for sub_item in sub_tree[key]:
                        self.dict_to_list(
                            sub_tree=sub_item,
                            current_list=current_list + [key],
                            items_list=items_list
                        )
                elif isinstance(sub_tree[key], dict):
                    self.dict_to_list(
                        sub_tree=sub_tree[key],
                        current_list=current_list + [key],
                        items_list=items_list
                    )
                else:
                    items_list.append(current_list + [key] + [sub_tree[key]])
        except:  # Tree leaf.
            items_list.append(current_list + [sub_tree])

        return items_list

    def extract_entries(self) -> [[(str, object)]]:
        """
        Extracts entries from a dictionary.

        Returns
        -------
        entries: [[(str, object)]]
            List of key-value items list.
        """
        entries = []

        for parent in self.dict_list:
            key_value_tuples = []

            for child in self.dict_to_list(sub_tree=parent, current_list=[], items_list=[]):
                key_parts = child[:-1]
                key = self.key_sep.join(key_parts)
                value = child[-1]
                key_value_tuples.append((key, value))

            entries.append(key_value_tuples)

        return entries

    @staticmethod
    def get_nth_element(
        items: [(str, object)],
        element: str,
        nth: int = 1
    ) -> ((str, object), bool):
        """
        Get nth element (occurrence) from items list.

        Parameters
        ----------
        items: [(str, object)]
            Items list.
        element: str
            Item key.
        nth: int
            Nth element position.

        Returns
        -------
        nth_element, index_out_of_bounds: ((str, object), bool)
            Nth element, and whether it was not found.
        """
        assert nth >= 1, f"'nth' ({nth}) must be >= 1."

        occurrences = [i for i in items if i[0] == element]
        n_occurrences = len(occurrences)

        if n_occurrences:
            index_out_of_bounds = True if nth > n_occurrences else False
            nth_element = occurrences[min(nth, n_occurrences) - 1]
        else:
            nth_element = None
            index_out_of_bounds = True

        return nth_element, index_out_of_bounds

    def to_tuples(self) -> ([str], [tuple]):
        """
        Convert JSON semi-structured data into structured tuples data.

        Returns
        -------
        keys, values: ([str], [tuple])
            List of keys and values.

        Examples
        --------
        data = {
            "values":
            [
                {
                    "A": 0,
                    "B": 1,
                    "C": 2
                },
                {
                    "C": {
                        "E": 3,
                        "F": 4
                    },
                    "D": [
                        {
                            "G": 5
                        },
                        {
                            "H": 6
                        }
                    ]
                }
            ]
        }

        self.dict_list = data['values']

            ... return (
                    ["A", "B", "C", "C_E", "C_F", "D_G", "D_H"],
                    [
                        (0, 1, 2, None, None, None, None),
                        (None, None, None, 3, 4, 5, 6)
                    ]
                )
        """
        LOGGER.info(f"Extracting values tuples from JSON file...")
        entries = self.extract_entries()
        keys = list(
            OrderedDict.fromkeys(
                [
                    key_value_tuple[0]
                    for samples in entries
                    for key_value_tuple in samples
                ]
            )
        )

        n_entries = len(entries)
        n_keys = len(keys)
        values = []

        for tuples, index in zip(entries, range(1, n_entries + 1)):
            LOGGER.debug(f"Processing values from entry {index}/{n_entries} ({((index / n_entries) * 100):.2f}%)...")

            for i in range(1, len(tuples) + 1):
                index_out_of_bounds_count = 0
                row = []

                for c in keys:
                    key_value_tuple, index_out_of_bounds = self.get_nth_element(items=tuples, element=c, nth=i)
                    row.append(key_value_tuple[1]) if key_value_tuple else row.append(None)

                    if index_out_of_bounds:
                        index_out_of_bounds_count += 1

                if index_out_of_bounds_count == n_keys:
                    break

                if row.count(None) != n_keys:
                    values.append(row)

        LOGGER.info(f"Successfully extracted values tuples from JSON file!")

        return keys, values

定义main方法以显示示例。

代码语言:javascript
复制
from datetime import date, datetime


class B:
    def __init__(self) -> B:
        self.data = {'a': {'b': [{'c': 0}, {'d': 1}]}}


class A:
    def __init__(self) -> A:
        self.name = "my_name"
        self.attr = "my_attr"
        self.b = B()


def main(dump_objects: bool) -> None:
    data = {'values': [{'A': A(), 'C': 3, 'D': date.today(), 'E': datetime.now(), 'F': {'G': {'H': 8}}}]}
    json_data = JSON(dict_list=data['values'], dump_objects=dump_objects)

    print("JSON to tuples test:\n")
    for i, d in enumerate(json_data.dict_list, start=1):
        print(f"d{i} = {d}\n")

    keys, values = json_data.to_tuples()

    print(f"\nKeys:")
    for i, key in enumerate(keys, start=1):
        print(f"\t{i}. {key}")

    print(f"\nValues:")
    for i, row in enumerate(values, start=1):
        print(f"\t{i}:")

        for j, value in enumerate(row, start=1):
            print(f"\t\t{j}. {value} ({type(value)})")

示例1:不转储对象

调用main方法。

代码语言:javascript
复制
main(dump_objects=False)

输出:

代码语言:javascript
复制
    JSON to tuples test:

    d1 = {'A': '<__main__.A object at 0x000002002F436290>', 'C': 3, 'D': datetime.date(2022, 2, 3), 'E': datetime.datetime(2022, 2, 3, 15, 54, 4, 874847), 'F': {'G': {'H': 8}}}

    INFO:__main__:Extracting values tuples from JSON file...
    DEBUG:__main__:Processing values from entry 1/1 (100.00%)...
    INFO:__main__:Successfully extracted values tuples from JSON file!

    Keys:
            1. A
            2. C
            3. D
            4. E
            5. F_G_H

    Values:
            1:
                    1. <__main__.A object at 0x000002002F436290> (<class 'str'>)
                    2. 3 (<class 'int'>)
                    3. 2022-02-03 (<class 'datetime.date'>)
                    4. 2022-02-03 15:54:04.874847 (<class 'datetime.datetime'>)
                    5. 8 (<class 'int'>)

示例2:转储对象

调用main方法。

代码语言:javascript
复制
main(dump_objects=True)

输出:

代码语言:javascript
复制
    JSON to tuples test:

    d1 = {'A': {'name': 'my_name', 'attr': 'my_attr', 'b': {'data': {'a': {'b': [{'c': 0}, {'d': 1}]}}}}, 'C': 3, 'D': '2022-02-03', 'E': '2022-02-03T15:55:29.014941', 'F': {'G': {'H': 8}}}

    INFO:__main__:Extracting values tuples from JSON file...
    DEBUG:__main__:Processing values from entry 1/1 (100.00%)...
    INFO:__main__:Successfully extracted values tuples from JSON file!

    Keys:
            1. A_name
            2. A_attr
            3. A_b_data_a_b_c
            4. A_b_data_a_b_d
            5. C
            6. D
            7. E
            8. F_G_H

    Values:
            1:
                    1. my_name (<class 'str'>)
                    2. my_attr (<class 'str'>)
                    3. 0 (<class 'int'>)
                    4. 1 (<class 'int'>)
                    5. 3 (<class 'int'>)
                    6. 2022-02-03 (<class 'str'>)
                    7. 2022-02-03T15:55:29.014941 (<class 'str'>)
                    8. 8 (<class 'int'>)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26595840

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档