【问题标题】:How to search through structure iteratively?如何迭代地搜索结构?
【发布时间】:2020-02-27 04:30:03
【问题描述】:

[Python 3.7]

我查询的前提:

LADDER 逻辑程序中获取后端代码并从 XML 文件中重建数据。

我有一个启动步骤S1。树代表一个序列。 我想在树中迭代循环并在两个步骤之间创建该路径的元素的有序列表(S1 是第一个)。

[graphical example]

           [S1]
            |          
          B3|_________ 
            |         |
           [T1]     [T7]
            |         |
            |       B4|
            |         |
           [S2]     [S3]

理想的逻辑流程示例:

[S1] --> [B3] --> [T1] --> [S2]
          |
          \--> [T7] --> [B4] --> [S3]

这个结果(理想情况下):

1: [ [S1], [B3], [T7], [B4], [S3] ]
2: [ [S1], [B3], [T1], [S2] ]

需要知道的一些事情:

  • 结束步骤可以直接来自转换或分支
  • 每个元素在其类型中都有一个唯一标识符
  • 列表中的每个元素都与唯一 ID 相关,并包含有关下一个连接的信息

数据:

STEPS
con_steps = [[['StepRef', {'Number': '1'}], ['BranchRef', {'Number': '3', 'In': '0'}]], [['StepRef', {'Number': '3'}], ['BranchRef', {'Number': '11', 'In': '0'}]], [['StepRef', {'Number': '5'}], ['BranchRef', {'Number': '12', 'In': '0'}]], [['StepRef', {'Number': '4'}], ['BranchRef', {'Number': '13', 'In': '0'}]], [['StepRef', {'Number': '2'}], ['BranchRef', {'Number': '14', 'In': '0'}]]]

BRANCHES
con_brans = [[['BranchRef', {'Number': '3', 'Out': '0'}], ['TransitionRef', {'Number': '1'}]], [['BranchRef', {'Number': '3', 'Out': '1'}], ['TransitionRef', {'Number': '7'}]], [['BranchRef', {'Number': '4', 'Out': '0'}], ['StepRef', {'Number': '3'}]], [['BranchRef', {'Number': '11', 'Out': '0'}], ['TransitionRef', {'Number': '3'}]], [['BranchRef', {'Number': '11', 'Out': '1'}], ['TransitionRef', {'Number': '5'}]], [['BranchRef', {'Number': '12', 'Out': '0'}], ['TransitionRef', {'Number': '6'}]], [['BranchRef', {'Number': '12', 'Out': '1'}], ['TransitionRef', {'Number': '8'}]], [['BranchRef', {'Number': '13', 'Out': '0'}], ['TransitionRef', {'Number': '4'}]], [['BranchRef', {'Number': '13', 'Out': '1'}], ['TransitionRef', {'Number': '9'}]], [['BranchRef', {'Number': '14', 'Out': '0'}], ['TransitionRef', {'Number': '2'}]], [['BranchRef', {'Number': '14', 'Out': '1'}], ['TransitionRef', {'Number': '10'}]]]

TRANSITIONS
con_trans = [[['TransitionRef', {'Number': '2'}], ['BranchRef', {'Number': '4', 'In': '0'}]], [['TransitionRef', {'Number': '7'}], ['BranchRef', {'Number': '4', 'In': '1'}]], [['TransitionRef', {'Number': '3'}], ['StepRef', {'Number': '4'}]], [['TransitionRef', {'Number': '5'}], ['StepRef', {'Number': '5'}]], [['TransitionRef', {'Number': '1'}], ['StepRef', {'Number': '2'}]], [['TransitionRef', {'Number': '8'}], ['StepRef', {'Number': '2'}]], [['TransitionRef', {'Number': '6'}], ['StepRef', {'Number': '1'}]], [['TransitionRef', {'Number': '9'}], ['StepRef', {'Number': '2'}]], [['TransitionRef', {'Number': '4'}], ['StepRef', {'Number': '1'}]], [['TransitionRef', {'Number': '10'}], ['StepRef', {'Number': '1'}]]]

目标:

选择一个起始步骤并查找所有可能的路径并创建该路径元素的有序列表。 能够遍历所有步骤并最终得到一个包含所有连接的数组。

我的尝试:

    S1 = []
    for i in con_steps:
        if i[0][1]['Number'] == '1':
            print(i)
            #save branch then cont.
            bran1 = i[1][1]['Number']

            tran1 = []
            for j in con_brans:
                if j[0][1]['Number'] == bran1:
                    print(j)
                    tran1.append(j[1][1]['Number'])


                    for k in tran1:
                        bran2 = []
                        for m in con_trans:
                            if m[0][1]['Number'] == k:
                                print(m)

                                if m[1][0] == 'StepRef':
                                    print('last step', m)
                                    S1.append(['1', m[1][1]['Number']])
                                else:
                                    bran2.append(j[1][1]['Number'])
                                    print('continue on', m)

【问题讨论】:

  • 这里有什么问题?
  • @Barmar 如何对链接的树/结构的元素进行迭代搜索并返回所有可能的路径。
  • 维基百科Tree traversal
  • 你需要递归,而不仅仅是嵌套循环
  • @Barmar 谢谢,很有用

标签: python python-3.x algorithm loops for-loop


【解决方案1】:

如果您不想使用递归,您可以使用 deque 对象(来自集合)获得相同的结果,该对象可以充当堆栈并避免递归深度限制(也更易于调试):

def findNodes(nodeType,number):
    nodeList = {"StepRef":con_steps,"BranchRef":con_brans, "TransitionRef":con_trans}[nodeType]
    return [node for node in nodeList if node[0][1]["Number"] == number]

from collections import deque
def getPaths(start):
    q         = deque()
    result    = []
    firstNode = findNodes("StepRef",start)
    q.append(firstNode)
    seen      = set()
    while q:
        path       = q.popleft()
        nodeLink   = path[-1][1]
        linkType   = nodeLink[0]
        linkNumber = nodeLink[1]["Number"]            
        nextNodes  = findNodes(linkType,linkNumber)
        leafKey    = (path[-1][0][0],path[-1][0][1]["Number"])
        if leafKey in seen or not nextNodes:
            result.append(path)
            continue
        if leafKey[0] == "StepRef":
            seen.add(leafKey)
        for nextNode in nextNodes:
            q.append(path+[nextNode])
    return result

输出:

paths = getPaths("1")
for path in paths:
    print( [f"{p[0][0][:1]}{p[0][1]['Number']}" for p in path])


['S1', 'B3', 'T1', 'S2', 'B14', 'T10', 'S1']
['S1', 'B3', 'T1', 'S2', 'B14', 'T2', 'B4', 'S3']
['S1', 'B3', 'T7', 'B4', 'S3', 'B11', 'T3', 'S4', 'B13', 'T4', 'S1']
['S1', 'B3', 'T7', 'B4', 'S3', 'B11', 'T3', 'S4', 'B13', 'T9', 'S2']
['S1', 'B3', 'T7', 'B4', 'S3', 'B11', 'T5', 'S5', 'B12', 'T6', 'S1']
['S1', 'B3', 'T7', 'B4', 'S3', 'B11', 'T5', 'S5', 'B12', 'T8', 'S2']

顺便说一句,您的数据结构很难操作。您应该考虑为层次结构中的所有节点使用一个公共对象类,以便遍历和操作不需要太多索引。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-30
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 2013-09-25
    • 2015-09-05
    • 1970-01-01
    • 2017-03-29
    相关资源
    最近更新 更多