如何将二进制表达式树从字符串转换为嵌套列表? 解决方案解决方案

问题描述

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

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

问题:

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

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

解决方法

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

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

注意:没有接受过正式的 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_6"],"param_7"],"param_4","param_7"]
]

示例 2

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

示例 3

[
    [
        ["param1"],["param2","param6"],"param7"]
    ]
]

在此过程中存在一些痛点 - 在我试图解决问题时遇到困难并最终重复工作的地方。

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

在我在库中找到我想要的东西之前,我花了大量时间构建解析器来将字符串转换为二元表达式树。

解决方案

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

意外边缘情况

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

左成员中的多个 Like 表达式

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

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

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

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

解决方案

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

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

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

关键外卖

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