Как рекурсивно решить проблему пути к каталогу в Python? - PullRequest
0 голосов
/ 05 апреля 2019

Я выполняю вызовы API REST для извлечения папок из библиотеки документов SharePoint.

Я хочу рекурсивно получить все пути к папкам во всем дереве каталогов.

Я написал функциючтобы получить список подпапок из данной папки, но я не уверен, как пройти до N-го каталога и получить все пути к папкам.

Предположим, например, что текущая структура библиотеки документов SharePoint представляет собойследующий JSON (fo = папка; f = файл):

{
  "root": [
    {
      "fo1": {
        "fo1": "f1",
        "fo2": ["f1", "f2"]
      },
      "fo2": ["fi1", "fi2"]
    },
    "fi1","fi2"]
}

Из приведенного выше примера я хочу получить список путей ко всем папкам / каталогам: Например, вывод должен быть:

["/root/fo1/", "/root/fo1/fo1/", "/root/fo1/fo2/", "/root/fo2/"]

Поскольку это вызов API REST, поэтому я не знаю структуру заранее, пока не выполню запрос на получение подпапок, а затем зайду в каждую подпапку, чтобы получить соответствующую подпапку.

Настоящее (следующее)Функция, которую я написал, - это получение данных до уровня 1 (подпапка, так как она основана на внутренней итерации, а не на рекурсии), как мне получить решение на основе рекурсии, чтобы получитьБудут ли уникальные пути к папкам в виде списка?

def print_root_contents(ctx):

    try:
        list_object = ctx.web.lists.get_by_title('Documents')
        folder = list_object.root_folder
        ctx.load(folder)
        ctx.execute_query()

        folders = folder.folders
        ctx.load(folders)
        ctx.execute_query()

        for myfolder in folders:
            print("For Folder : {0}".format(myfolder.properties["Name"]))
            folder_list, files_list = print_folder_contents(ctx, myfolder.properties["Name"])
            print("Sub folders - ", folder_list)
            print("Files - ", files_list)

    except Exception as e:
        print('Problem printing out library contents: ', e)


def print_folder_contents(ctx, folder_name):

    try:
        folder = ctx.web.get_folder_by_server_relative_url("/sites/abc/Shared Documents/"+folder_name+"/")
        ctx.load(folder)
        ctx.execute_query()

        # Folders
        fold_names = []
        sub_folders = folder.folders
        ctx.load(sub_folders)
        ctx.execute_query()
        for s_folder in sub_folders:
            # folder_name = folder_name+"/"+s_folder.properties["Name"]
            # print("Folder name: {0}".format(folder.properties["Name"]))
            fold_names.append(s_folder.properties["Name"])

        return fold_names

    except Exception as e:
        print('Problem printing out library contents: ', e)

В последней функции (print_folder_contents), описанной выше, я не могу сформировать рекурсивную логику, чтобы рекурсивно продолжать добавлять папки и подпапки и останавливать ее, когда больше нетпапки внутри n-й папки и переходите к следующей папке одного уровня на один уровень выше.

Найти его действительно сложным.Любая помощь?

1 Ответ

0 голосов
/ 05 апреля 2019

Вы можете использовать функцию генератора, которая перебирает элементы dict и выдает ключи dict, а также возвращает ключи, объединенные с путями, сгенерированными из рекурсивных вызовов, и, если задан список, рекурсивно выдает то, что сгенерировано из рекурсивных вызовов элементов списка:

def paths(d):
    def _paths(d):
        if isinstance(d, dict):
            for k, v in d.items():
                yield k + '/'
                for p in _paths(v):
                    yield '/'.join((k, p))
        elif isinstance(d, list):
            for i in d:
                yield from _paths(i)
    return ['/' + p for p in _paths(d)]

, поэтому с учетом:

d = {
  "root": [
    {
      "fo1": {
        "fo1": "f1",
        "fo2": ["f1", "f2"]
      },
      "fo2": ["fi1", "fi2"]
    },
    "fi1","fi2"]
}

paths(d) возвращает:

['/root/', '/root/fo1/', '/root/fo1/fo1/', '/root/fo1/fo2/', '/root/fo2/']

Обратите внимание, что ожидаемый вывод должен включать '/root/', поскольку корневая папка должна бытьдопустимая папка.

...