简体   繁体   English

如何在 python 中创建具有属性的嵌套文件夹?

[英]How can I create nested folders with attributes in python?

I'm a beginner programmer, and I just started learning about Nested lists and dictionaries.我是一个初学者程序员,我刚开始学习嵌套列表和字典。 I have a task to create a system of files, with class Directory and it's attributes.我的任务是使用 class 目录及其属性创建文件系统。

class Directory:
    def __init__(self, name: str, parent: Optional['Directory'], children: List[Optional['Directory']]):
        self.name = name
        self.parent = parent
        self.children = children

I'm supposed to build a function to create this system of files recursively, given root and it's directories from dictionary.我应该构建一个 function 以递归方式创建这个文件系统,给定 root 及其字典中的目录。 Parent is a directory which includes current dir as one of his children. Parent 是一个目录,其中包含当前目录作为他的孩子之一。 Any dir which doesn't have any children is supposed to be an empty directory.任何没有子目录的目录都应该是一个空目录。

    "root": ["dirA", "dirB"],          
    "dirA": ["dirC"],
    "dirC": ["dirH", "dirG"],
    "dirB": ["dirE"]
    "dirG": ["dirX", "dirY"]}

I've been trying to do this and I think I know how to create directories recursively, however I have no idea what to put in dir.parent place without any additional imports.我一直在尝试这样做,我想我知道如何递归地创建目录,但是我不知道在没有任何额外导入的情况下将什么放在 dir.parent 位置。 With root, there's no problem because it is None but further in process I don't know how to place child's parent (which is supposed to be Directory) as one of his attributes since I'm going recursively from there.使用root,没有问题,因为它是None,但在进一步的过程中,我不知道如何将孩子的父母(应该是Directory)作为他的属性之一,因为我将从那里递归。 Do you have any idea how to do that?你知道怎么做吗? Here's code which I have so far:这是我到目前为止的代码:

def create_system(system: Dict[str, List[str]], parent_children: List[str]) -> Optional[List[Optional['Directory']]]:
    children: List[Optional['Directory']] = []
    for child in parent_children:
        if child in system.keys():
            children.append(Directory(child, parent, create_system(system, list(system.get(child)))))
        else:
            children.append(Directory(child, parent, []))
    return children

def root(system: Dict[str, List[str]]) -> Optional['Directory']:
    return Directory("root", None, create_system(system, list(system.get("root"))))

Thank you for any responses!感谢您的任何回复!

Your goal is to transform the dictionary您的目标是转换字典

system = {
    "root": ["dirA", "dirB"],          
    "dirA": ["dirC"],
    "dirC": ["dirH", "dirG"],
    "dirB": ["dirE"]
    "dirG": ["dirX", "dirY"]
}

into the following tree:进入以下树:

            root
           /    \
        dirA    dirB
        /         \
      dirC        dirE
     /   \
   dirH  dirG
         /   \
       dirX  dirY

Hopefully, it's clear that the return value of the process can be just the root.希望很明显,该过程的返回值可以只是根。 To guarantee that you hit every folder only after its parent has been created, you can use either a stack-based BFS approach, or a recursive DFS approach.为确保仅在创建父文件夹后才访问每个文件夹,您可以使用基于堆栈的 BFS 方法或递归 DFS 方法。

Let's look at a simple BFS approach:让我们看一个简单的 BFS 方法:

def create_system_bfs(system):
    root = Directory('root', None, [])
    stack = [root]  # in practice, use collections.deque([root])

    while stack:
        current = stack.pop(0)
        for child in system.get(current.name, []):
            d = Directory(child, current, [])
            current.children.append(d)
            stack.append(d)

    return root

The DFS version of that could be something like:其 DFS 版本可能类似于:

def create_system_dfs(system):
    def create_node(name, parent):
        d = Directory(name, parent, [])
        d.children = [create_node(child, d) for child in system.get(name, [])]
        return d
    return create_node('root', None)

Keep in mind that there are other possible approaches.请记住,还有其他可能的方法。 In both cases, the create_root method is completely unnecessary.在这两种情况下, create_root方法都是完全没有必要的。 The BFS approach is limited only by available heap memory. BFS 方法仅受可用堆 memory 的限制。 The DFS approach may also be limited by stack size. DFS 方法也可能受到堆栈大小的限制。

Before get all tangled up in classes we can think in terms of an ordinary function -在上课之前,我们可以考虑一个普通的 function -

def paths(t, init="root"):
  def loop(q, path):
    if isinstance(q, dict):
      for (dir, v) in q.items():
        yield from loop(v, [*path, dir])
    elif isinstance(q, list):
      for dir in q:
        yield from loop \
          ( t[dir] if dir in t else None
          , [*path, dir]
          )
    else:
      yield "/".join(path)
  yield from loop(t[init], ["."])

Using paths is easy, simply call it on your input tree -使用paths很容易,只需在input树上调用它 -

input = {
  "root": ["dirA", "dirB"],          
  "dirA": ["dirC"],
  "dirC": ["dirH", "dirG"],
  "dirB": ["dirE"],
  "dirG": ["dirX", "dirY"]
}

for path in paths(input):
  print(path)
./dirA/dirC/dirH
./dirA/dirC/dirG/dirX
./dirA/dirC/dirG/dirY
./dirB/dirE

Using paths allows us to easily create the directories we need -使用paths可以让我们轻松创建我们需要的目录 -

import os

for path in paths(input):
  os.makedirs(path)

输出

This is an opportunity to learn about reusable modules and mutual recursion.这是一个了解可重用模块和相互递归的机会。 This solution in this answer solves your specific problem without any modification of the modules written in another answer .此答案中的此解决方案解决了您的特定问题,而无需对另一个答案中编写的模块进行任何修改。 The distinct advantage of this approach is that tree has zero knowledge of your node shape and allows you to define any output shape.这种方法的明显优势是tree对节点形状的了解为零,并允许您定义任何 output 形状。

Below we create a tree using plain dict with name , parent , and children properties.下面我们使用具有nameparentchildren属性的普通dict创建一棵树。 tree does not make this choice for you. tree不会为您做出这个选择。 A different structure or a custom class can be used, if desired -如果需要,可以使用不同的结构或自定义 class -

from tree import tree

input = {
  None: ["dirA", "dirB"],          
  "dirA": ["dirC"],
  "dirC": ["dirH", "dirG"],
  "dirB": ["dirE"],
  "dirG": ["dirX", "dirY"]
}

result = tree \
  ( flatten(input)
  , parent
  , lambda node, children:
      dict \
        ( name=name(node)
        , parent=parent(node)
        , children=children(name(node))
        )
  )

print(result)
[
  {
    "name": "dirA",
    "parent": None,
    "children": [
      {
        "name": "dirC",
        "parent": "dirA",
        "children": [
          {
            "name": "dirH",
            "parent": "dirC",
            "children": []
          },
          {
            "name": "dirG",
            "parent": "dirC",
            "children": [
              {
                "name": "dirX",
                "parent": "dirG",
                "children": []
              },
              {
                "name": "dirY",
                "parent": "dirG",
                "children": []
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "name": "dirB",
    "parent": None,
    "children": [
      {
        "name": "dirE",
        "parent": "dirB",
        "children": []
      }
    ]
  }
]

In order to use tree , we defined a way to flatten the input nodes -为了使用tree ,我们定义了一种flatten输入节点的方法 -

def flatten(t):
  seq = chain.from_iterable \
    ( map(lambda _: (_, k), v)
        for (k,v) in input.items()
    )
  return list(seq)

print(flatten(input))
[ ('dirA', None)
, ('dirB', None)
, ('dirC', 'dirA')
, ('dirH', 'dirC')
, ('dirG', 'dirC')
, ('dirE', 'dirB')
, ('dirX', 'dirG')
, ('dirY', 'dirG')
]

And we also defined the primary key and foreign key.而且我们还定义了主键和外键。 Here we use name and parent , but you can choose whichever names you like -这里我们使用nameparent ,但你可以选择任何你喜欢的名字 -

def name(t):
  return t[0]

def parent(t):
  return t[1]

To learn more about the tree module and some of its benefits, see the original Q&A要了解有关tree模块及其一些好处的更多信息,请参阅原始问答

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在Python中创建多个嵌套文件夹? - How to create multiple nested folders in Python? 如何在DynamoDB(Python)中的嵌套属性上使用FilterExpression? - How can i use FilterExpression over Nested Attributes in DynamoDB (Python)? 如何在 Python 中模拟具有嵌套属性的对象? - How can I mock object with nested attributes in Python? Python-如何在新创建的目录中创建多个文件夹? - Python - How can I create multiple folders in a newly created directory? 如何创建递归Python脚本对文件和文件夹进行排序? - How Can I Create a Recursive Python Script to Sort Files and Folders? 如何在Maya python API中创建矢量类型的属性? - how can i create vector type of attributes in maya python api? 在 Python 中,我如何在 class 中创建一个方法来为属性赋值 - In Python how can I create a method in a class that assigns values to attributes 如何在python中创建用于设置对象属性的模板函数? - How can I create a template function for setting object attributes in python? 如何基于 FTP 文件夹树创建 Python 嵌套字典 - How to create a Python nested dictionary based on a FTP tree of folders 如何在多个文件夹中创建相同的多个文件夹? - How can I create the same multiple folders in many Folders?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM