【问题标题】:How Can I Convert a Binary Expression Tree from a String to a Nested List?如何将二进制表达式树从字符串转换为嵌套列表?
【发布时间】:2021-07-23 19:48:35
【问题描述】:

我最初的问题是理解我什至试图做什么。我真的不知道如何 寻求帮助,因为我并不真正明白这是我想要做的。我已经在我的回答中详细解释了我做了什么,以及我是如何做到的。我也发布了我的代码。

在使用 C# 构建 PowerShell 之前,我花了一段时间在 PowerShell 中进行原型设计。我希望这对其他人有帮助。

问题:

如何将"(Foo1 && Bar1 && (Foo2 || Bar2) && (Foo3 || Foo4))" 之类的字符串转换为这样的列表:

[
   ["Foo1", "Bar1", "Foo2", "Foo3"],
   ["Foo1", "Bar1", "Foo2", "Foo4"],
   ["Foo1", "Bar1", "Bar2", "Foo3"],
   ["Foo1", "Bar1", "Bar2", "Foo4"]
]

【问题讨论】:

    标签: c# .net .net-core expression-trees


    【解决方案1】:

    转换一个字符串表示二进制表达式树到所有可能组合的嵌套字符串列表

    我正在尝试构建一个类,该类允许我将字符串格式的二进制表达式树(请参见下面的输入示例)转换为所有可能值组合的嵌套列表。开始时,我不知道这是一个二叉表达式树,因此也不知道如何找到我要查找的内容。

    注意: 没有接受过正规的 CS 培训,也没有接受过正规的编程教育。我是作为一名系统管理员进入 IT 行业的,除了在青少年时期曾短暂使用 C++ 进行编程外,多年的 HTML/CSS 从未真正搞砸过已编译的软件。我写了很多脚本,并花了大约五年时间掌握 PowerShell——这仍然是我最舒服的地方。我的大部分原型设计都是在 PowerShell (7.1.3) 中完成的。

    你可以在github上看到My Code

    输入示例

    示例 1

    "(param_1 && param_2 && (param_3 || param_4) && (param_5 || param_6 || param_7))"
    

    示例2

    "((param1 && (param2 || param3 || param4)) && param5)"
    

    示例 3

    "(param1 || (param2 && param3 && param4 && (param5 || param6 || param7)))"
    

    预期输出

    示例1

    [
        ["param_1","param_2","param_3","param_5"],
        ["param_1","param_2","param_3","param_6"],
        ["param_1","param_2","param_3","param_7"],
        ["param_1","param_2","param_4","param_5"],
        ["param_1","param_2","param_4","param_6"],
        ["param_1","param_2","param_4","param_7"]
    ]
    

    示例 2

    [
        [
            ["param1", "param2", "param5"],
            ["param1", "param3", "param5"], 
            ["param1", "param4", "param5"]
        ]
    ]
    

    示例 3

    [
        [
            ["param1"],
            ["param2", "param3", "param4", "param5"],
            ["param2", "param3", "param4", "param6"],
            ["param2", "param3", "param4", "param7"]
        ]
    ]
    

    在此过程中遇到了一些痛点——在我试图解决问题的过程中,我被卡住并最终重复工作。

    将字符串转换为二进制表达式树

    在我在库中找到我要查找的内容之前,我花费了大量时间构建解析器以将字符串转换为二进制表达式树。

    解决方案

    最终我找到了 NRECO 的 LambdaParser library (github),这减轻了很多压力(尽管我很确定我构建的东西在这个意义上是完整的)。

    意外的边缘情况

    虽然这看起来微不足道且显而易见,但我在遍历树构建列表时一直遇到问题。

    左成员中的多个相似表达式

    最初我没有考虑左侧成员包含多个类似表达式(ie“this AND that AND that too”)的情况,这会导致构建不完整的列表。

    节点不包含成员表达式 (?)

    我以为我已经完成了这个工具。我得到了一个可能的表达式列表(超出了我一直在测试的少数表达式),然后……它崩溃了。我发现我没有考虑当前处理节点包含两个二进制表达式的情况。 (而到目前为止,我构建它的印象是一侧或另一侧始终是成员表达式)

    一旦我遇到了这个问题,我就意识到出了什么问题,并且已经花了很多时间在这件事上,我知道什么需要做,只是我不知道该怎么做去做吧。

    解决方案

    当出现其中一个节点时,我必须根据与下一个成员表达式深度最接近的表达式创建两条不同的路径。从那里它将创建两条路径,在相对节点上向下处理直到到达“底部”。我们可以将每条路径的每次迭代添加到主输出。鉴于此函数是递归的,它不应该发生多少次

    注意: 在我的解决方案中,当它遇到不包含成员表达式的二进制表达式时,它确实目前仍假定一个这两个表达式中的一个将是成员表达式。也就是说,如果我理解这种表达的性质,我认为这应该不是问题

    注意:我找到了一些参考资料,包括这个 Question 关于做类似 F# 的事情,但我似乎无法将其应用于我的问题。

    关键要点

    对我来说,这是一次非常有用的学习经历,我遇到了一个涉及核心数据结构的现实问题。由于我没有(编程)算法或数据结构的真正背景,这教会了我很多东西,尽管它是一个巨大的 PITA,但它教会了我很多关于如何在未来解决这些类型的问题。如果您有时间,我会鼓励任何人尝试自己构建它。感谢阅读。

    【讨论】:

      猜你喜欢
      • 2016-02-08
      • 1970-01-01
      • 2021-05-01
      • 1970-01-01
      • 2019-04-24
      • 2021-11-25
      • 2020-06-20
      • 1970-01-01
      • 2021-10-28
      相关资源
      最近更新 更多