найти все возможные пути в дереве в python - PullRequest
1 голос
/ 04 мая 2020

Я пытаюсь создать список всех возможных путей в дереве. У меня есть следующая структура (подмножество из БД):

text = """
1,Product1,INVOICE_FEE,
3,Product3,INVOICE_FEE,
7,Product7,DEFAULT,
2,Product2,DEFAULT,7
4,Product4,DEFAULT,7
5,Product5,DEFAULT,2
"""

, где столбцы: ID, имя продукта, тип счета, идентификатор ссылки на родителя. Я хотел бы создать список со всеми возможными путями, как в примере:

[[Product1],[Product3],[Product7,Product2,Product5],[Product7,Product4]]

Я делаю следующее:

lines = [ l.strip() for l in text.strip().splitlines() ]
hierarchy = [ tuple(l.split(',')) for l in lines ]

parents = defaultdict(list)
for p in hierarchy:
    parents[p[3]].append(p)

для создания дерева, а затем я хотел бы найти все paths:

def pathsMet(parents, node=''):
    childNodes = parents.get(node)
    if not childNodes:
        return []
    paths = []
    for ID, productName, invoiceType, parentID in childNodes:
        paths.append([productName] + pathsMet(parents, ID))
    return paths

print(pathsMet(parents))

Результат, который я получил, следующий:

[['FeeCashFlow1'], ['FeeCashFlow3'], ['PrincipalCashFlow7', ['AmortisationCashFlow3', ['AmortisationCashFlow2']], ['AmortisationCashFlow4']]]

Как исправить код, чтобы получить следующий вывод:

[['FeeCashFlow1'], ['FeeCashFlow3'], ['PrincipalCashFlow7', 'AmortisationCashFlow3', 'AmortisationCashFlow2'], ['PrincipalCashFlow7','AmortisationCashFlow4']]

Ответы [ 2 ]

0 голосов
/ 04 мая 2020

Ваш код кажется правильным, за исключением того, что вы добавляете весь список к переменной paths вместо элементов списка.

Попробуйте эту модификацию:

def pathsMet(parents, node=''):
    childNodes = parents.get(node)
    if not childNodes:
        return [[]]
    paths = []
    for ID, productName, invoiceType, parentID in childNodes:
        for p in pathsMet(parents, ID):
            paths.append([productName] + p)
    return paths
0 голосов
/ 04 мая 2020

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

text = """
1,Product1,INVOICE_FEE,
3,Product3,INVOICE_FEE,
7,Product7,DEFAULT,
2,Product2,DEFAULT,7
4,Product4,DEFAULT,7
5,Product5,DEFAULT,2
"""

data  = [ line.split(",") for line in text.split("\n") if line.strip() ]
keys  = { k:name for k,name,*_ in data }  # to get names from keys
tree  = { k:{} for k in keys }            # initial tree structure with all keys
root  = tree[""] = dict()                 # tree root
for k,_,_,parent in data: 
    tree[parent].update({k:tree[k]})      # connect children to their parent

nodes = [[k] for k in root]  # cumulative paths of keys
paths = []                   # list of paths by name
while nodes:
    kPath = nodes.pop(0)
    subs  = tree[kPath[-1]]                         # get children
    if subs: nodes.extend(kPath+[k] for k in subs)  # accumulate nodes
    else   : paths.append([keys[k] for k in kPath]) # return path if leaf node

output:

print(paths)
[['Product1'], ['Product3'], ['Product7', 'Product4'], ['Product7', 'Product2', 'Product5']]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...