【问题标题】:Traverse a data structure in python that involves nesting lists and nesting dictionaries遍历python中涉及嵌套列表和嵌套字典的数据结构
【发布时间】:2022-01-24 18:36:07
【问题描述】:

我正在尝试遍历这种树,其想法是获取所有“标题”。注意这个结构可以变得更大,这意味着每个标题将来可以得到更多的子类别。有什么想法吗?

我正在尝试这样做:


def continue_searching(item):
    for i in len(item):
        if categories[i]["subcategories"]:
            continue_searching(i["subcategories"])
            print(i["subcategories"])


def give_titles(categories):
    for i in len(categories):
        if categories[i]["subcategories"]:
            continue_searching(i["subcategories"])
        print(i['title'])


categories = [
    {
        "title": "Food",
        "subcategories": [
            {"title": "Bread"},
            {
                "title": "Meat",
                "subcategories": [
                    {"title": "Pork",
                     "subcategories": [
                         {"title": "White Pork"},
                         {"title": "Red Pork"}
                     ]
                     },
                    {"title": "Beef"},
                ],
            },
            {"title": "Cheese"},
        ],
    },
    {"title": "Drinks"},
]

give_titles(categories)


预期输出:

Food
-Bread
-Meat
--Pork
---White Pork
---Red Pork
--Beef
-Cheese
Drinks

请注意,我没有使用递归,因为我不清楚何时停止调用并且我不想使调用堆栈饱和。

【问题讨论】:

  • 我不明白这个输出。为什么有3个“猪肉”?通过获取标题,您是否要将它们放入字典中?在列表中?它们已经在数据结构中。
  • 因为有三个值为“pork”的“title”键
  • 我认为你在猪肉条目中有一些额外的换行符。我的修正看起来对吗?
  • 您想打印书面输出吗?你想通过遍历来达到什么目标? @JohnKugelman 的更正是您尝试打印的实际输出吗?
  • 我执行代码时的想法是得到预期的输出,也就是说,打印键“title”的所有值

标签: python-3.x list dictionary


【解决方案1】:

定义这个函数:

def write_titles(cats, depth=0):
  for c in cats:
    print('-'*depth, c['title'])
    write_titles(c.get('subcategories', []), depth+1)

然后使用write_titles(categories) 调用它。

【讨论】:

    【解决方案2】:

    遍历和打印这样的数据结构通常是使用递归来完成的。

    对于您的代码,我们希望在数据结构的每一次进一步嵌套中重复调用一个函数。

    示例代码:

    def print_titles(categories, depth=0):
        for category in categories:
            print('-' * depth, category['title'])
            if 'subcategories' in category:
                print_titles(category['subcategories'], depth + 1)
    

    既然您已经改变了问题并希望有一个无递归的解决方案,那么最好的解决方案可能是使用这样的迭代器:

    def print_titles(categories):
        stack = [iter(categories)]
        while stack:
            iterator = stack.pop()
            for item in iterator:
                print("-" * len(stack), item['title'])
                if 'subcategories' in item:
                    stack.append(iterator)
                    stack.append(iter(item['subcategories']))
                    break
    

    【讨论】:

      【解决方案3】:

      你可以使用递归编程

      def get_all_titles(data, output=[]):
          if isinstance(data, dict):
                  output.append(data.get("title"))
                  data = data.get("subcategories", [])
          if isinstance(data, list):
                  for item in data:
                          get_all_titles(item)
          return output
      

      输出

      print(get_all_titles(categories))
      ['Food', 'Bread', 'Meat', 'Pork', 'White Pork', 'Red Pork', 'Beef', 'Cheese', 'Drinks']
      

      【讨论】:

        【解决方案4】:

        您定义的结构本质上是一个单独树的列表。

        我只是遍历了列表中的每个“树”,并对树进行了前序遍历。

        categories = [
        {
            "title":         "Food",
            "subcategories": [
                {"title": "Bread"},
                {
                    "title": "Meat",
                    "subcategories": [
                    {"title": "Pork",
                        "subcategories": [
                        {"title": "White Pork"},
                        {"title": "Red Pork"}
                        ]
                    },
                    {"title": "Beef"},
                    ],
                },
                {"title": "Cheese"},
                ],
        },
        {"title": "Drinks"},
        ]
        
        
        # What's really defined here is like a list of trees
        
        def preorder(root, depth):
            print("-" * depth + root["title"])
            if "subcategories" in root:
                for child in root["subcategories"]:
                    preorder(child, depth + 1)
        
        
        def printCategories(categories):
            for tree in categories:
                preorder(tree, 0)
            
        printCategories(categories)
        

        这个输出:

        Food
        -Bread
        -Meat
        --Pork
        ---White Pork
        ---Red Pork
        --Beef
        -Cheese
        Drinks
        

        由于您还提到您不想使用递归,因此只需使用您自己的堆栈执行遍历,如 here 所示。

        【讨论】:

          【解决方案5】:
          def all_titles(data, output=[]):
          
              if x(data, dict):
                      output.append(data.get("title"))
                      data = data.get("subcategories", [])
              
              if x(data, list):
                      for y in data:
                              all_titles(item)
              return
          

          【讨论】:

            猜你喜欢
            • 2021-03-19
            • 2015-12-06
            • 2013-07-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-03-22
            • 2012-07-09
            相关资源
            最近更新 更多