Вам может понадобиться, чтобы объяснить немного больше о том, как вы ожидали чтобы «сравнить» два объекта, но я собираюсь предположить, что ваша главная проблема в том, что вы хотите, чтобы превратить эту вложенную структуру каталогов в виде плоского списка путей Т.е. вы хотите эту вложенную структуру.
- folder2:
- subfolder1:
- deepfolder1
- deepfolder2
Чтобы получить плоский список из них:
folder2/subfolder1/deepfolder1
folder2/subfolder1/deepfolder2
Это форма «tree traversal».
Одна сложная часть здесь состоит в том, что обычно деревья представлены в виде списков списков, но ваш YAML смешивает ассоциативные массивы (AKA dicts или хэши) и списки. Таким образом, это делает код немного сложнее.
Вот рекурсивный обход дерева для данных, которые вы дали:
def traverse(t, prefix=None):
prefix = prefix or []
if len(t) == 0:
raise StopIteration
elif len(t) == 1:
first, rest = t[0], []
else:
first, rest = t[0], t[1:]
#walk first element
if isinstance(first, str):
#it's a single node
yield prefix + [first]
elif isinstance(first, list):
#it's a list of nodes
for element in first:
for tmp in traverse(element, prefix=prefix):
yield tmp
elif isinstance(first, dict):
#there's another level of nesting
for sub in first:
for tmp in traverse(first[sub], prefix=(prefix + [sub])):
yield tmp
#walk rest of elements recursively
for element in traverse(rest, prefix=prefix):
yield element
for expanded_path in traverse(tree):
print(expanded_path)
Если вы на Python 3.4 вы можете использовать yield from
для очистки «for tmp in ...: yield tmp
» части. Full code here.
Когда я бегу это на данные, которые я получаю:
['folder1']
['folder2', 'subfolder1', 'deepfolder1']
['folder2', 'subolder2']
['folder3']
['folder4']
Эти расширенные пути затем в том же формате, что и ваш path_elements
переменной, так что теперь мы можем сравнить их друг против друга.
Вы можете search SO или python recipes для лучшего алгоритма обхода дерева, шахта не может быть наиболее эффективным (есть limit to python's recursion depth, так что вам, возможно, придется использовать итеративный вариант в производстве).
Edit: В ответ на ваш комментарий: «вернуть„True“, если request_path находится в структуре дерева», вам просто нужно перебирает расширенные пути и посмотреть, если request_path совпадает с любым из них:
def compare(request_path, tree):
path_elements = parse.unquote_plus(request_path).split(sep)
for expanded_path in traverse(tree):
if expanded_path == path_elements:
return True
return False
Но это зависит от того, что находится в request_path
, полный URL (http://www.blah.com/foo/boo.txt) или абсолютный URL (/foo/boo.txt) или относительный URL (foo/boo.txt)? Если это так, вам может понадобиться очистить пути, прежде чем сравнивать их. Это все довольно легко сделать (поиск SO для расщепления путей и URL-адресов), ходьба по дереву - сложная часть.
спасибо до сих пор! Я добавил более конкретную цель на вопрос: return 'True', если request_path находится в древовидной структуре. – basbebe
Эта часть проста после того, как у вас есть список расширенных путей. Просто зациклируйте все расширенные пути и сравните каждый из них с request_path. Я отредактировал свой ответ с этой информацией. –