【问题标题】:Return result from arbitrarily nested xml tree sum从任意嵌套的 xml 树总和返回结果
【发布时间】:2019-06-04 15:21:56
【问题描述】:

我有以下代码在 xml 树上递归(?),它代表一个简单的等式:

root = etree.XML(request.data['expression'])

def addleafnodes(root):
    numbers = []
    for child in root:
        if root.tag != "root" and root.tag != "expression":
            print(root.tag, child.text)

            if child.tag != "add" and child.tag != "multiply":
                numbers.append(int(child.text))
                print("NUMBERS", numbers)
            elif child.tag == "add":
                numbers.append(np.sum(addleafnodes(child)))
                print("NUMBERS", numbers)
            elif child.tag == "multiply":
                numbers.append(np.prod(addleafnodes(child)))
                print("NUMBERS", numbers)
        print("NUMBERS", numbers)
        addleafnodes(child)
    return numbers

newresults = addleafnodes(root)
print("[NEW RESULTS]", newresults)

xml 是:

<root>
    <expression>
        <add>
            <add>
                <number>1</number>
                <number>2</number>
            </add>
            <multiply>
                <number>2</number>
                <number>3</number>
            </multiply>
            <add>
                <number>4</number>
                <number>5</number>
            </add>
            <number>3</number>
            <multiply>
                <number>1</number>
                <add>
                    <number>3</number>
                    <number>4</number>
                </add>
            </multiply>
        </add>
    </expression>
</root>

代码似乎一直工作到最后一个循环,当它重置数字列表并似乎再次启动该过程时,失败了。

我如何告诉 python (lxml) 在查看每个节点后停止?我可能错过了一些重要的事情!

【问题讨论】:

    标签: python-3.x recursion lxml


    【解决方案1】:

    首先,我认为您可以通过断言标签 某物,而不是它 不是 某物(例如,尝试删除 ! = 并替换为 ==)。

    一个问题是addleafnodes(child) 行返回了一些东西,然后被扔掉了。由于您可以获得返回的数字列表,应该添加/相乘/等等,您可以使用numbers.extend(somelist) 将这些添加到numbers 列表中。解释递归有点困难,所以如果你看一下代码,它可能会更有意义。我有时会在函数中添加一个depth 变量,并在每次我“递归”时递增它 - 这样,在打印信息时,可能更容易查看数字从哪个“级别”返回以及返回到何处。

    def addleafnodes(root):
        numbers = []
        for child in root:
            if child.tag == "number":
                numbers.append(int(child.text))
            elif child.tag == "add":
                numbers.append(np.sum(addleafnodes(child)))
            elif child.tag == "multiply":
                numbers.append(np.prod(addleafnodes(child)))
            else:
                numbers.extend(addleafnodes(child))
            print("NUMBERS: ", numbers)
        return numbers
    
    newresults = addleafnodes(root)
    print("[NEW RESULTS]", newresults)
    
    # outputs:
    NUMBERS:  [1]
    NUMBERS:  [1, 2]
    NUMBERS:  [3]
    NUMBERS:  [2]
    NUMBERS:  [2, 3]
    NUMBERS:  [3, 6]
    NUMBERS:  [4]
    NUMBERS:  [4, 5]
    NUMBERS:  [3, 6, 9]
    NUMBERS:  [3, 6, 9, 3]
    NUMBERS:  [1]
    NUMBERS:  [3]
    NUMBERS:  [3, 4]
    NUMBERS:  [1, 7]
    NUMBERS:  [3, 6, 9, 3, 7]
    NUMBERS:  [28]
    NUMBERS:  [28]
    [NEW RESULTS] [28]
    

    另一件事:您已选择允许&lt;add&gt;&lt;/add&gt; 中的数字列表。您也可以认为它只有 2 个数字,因为它是二元运算,然后依赖嵌套。显然同样适用于其他一元/二元/三元/.. 运算符。

    <add>
        <number>1</number>
        <add>
            <number>2</number>
            <number>3</number>
        </add>
    </add>
    

    那样,也许您可​​以消除 for 循环,但我不确定它是否会产生其他问题。 :-)

    【讨论】:

    • 太棒了!是的,我想我将开始使用深度计数器调试我的递归函数 :)
    • @Davtho1983 我在帖子中添加了一个额外的想法,您可以考虑。否则你可以用谷歌搜索抽象语法树和编程语言概念的一般理论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-11
    • 2022-12-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多