c# - 非结构化字符串连接策略

标签 c# algorithm

我有(不同长度的)非结构化字符串数组,我希望将它们连接成字符串表达式以便进行解析。一些例子可能是

a  +b              => a+b
a+  b              => a+b
a  +b   c  +d      => a+b, c+d
a+  b   c+  d      => a+b, c+d
a+  b  +c   d      => a+b+c, d
a  +b  +c   d      => a+b+c, d
a+  b+  c  +d      => a+b+c+d
a  +b  +c  +d      => a+b+c+d
a  +b+  c+  d      => a+b+c+d
a  +b   c   d      => a+b, c, d

注意:a、b、c 和 d 是为了简洁起见。它们实际上可以是任意长度的字符串。此外,它们的数量可能是任意数量……而不仅仅是 4 个。

请注意,该元素可以具有前导或尾随运算符,这些运算符将决定它是应该连接到数组中的前一个还是后一个项目,以决定它是应该独立还是应该成为下一个表达式的一部分。 (一元运算符也存在固有的歧义,并决定是否

a -b => a-b or a, -b

我确实有一个语法(反讽),我目前使用它来确定正在构建的表达式是否格式正确。所以我连接每个元素,一次一个,解析连接的结果以查看它是否格式正确。如果它的格式正确,我仍然需要继续使用元素,以防下一个元素有前导运算符。一旦我从解析器得到 2 个无效结果(或者数组没有更多元素),我就断定表达式(禁止最后 2 个连接)是有效的,存储它然后重新开始。 (我需要这样做,因为我需要知道有效的表达式是数组中特定元素的串联,因为这些元素映射回具有其他信息的对象。)

但这一切都让人觉得有点不对劲。例如在

的情况下
a +b +c +d 

a          => valid
a +b       => valid
a +b +c    => valid
a +b +c +d => valid

我会得到 4 个有效“信号”,但对于底层表达式只有最后一个是“真实”有效“信号”

我想知道是否有其他更优雅的策略来尝试确定我是否应该串联。例如,也许我没有完全使用解析器,或者可能有一些我不熟悉的模式匹配策略?

那么我应该如何解决这个问题呢?

提前致谢

小号

PS 我使用的是 C#,但我认为这在这种情况下不一定相关。

最佳答案

这应该可以,注意这段代码如何处理一元运算符

static List<string> GetExpressions(string[] stringArray)
    {
        const string operators = "+-*/=";
        const string unaryOps = "+-";
        var q = new Queue<string>(stringArray.Length*2);

        foreach (string s in stringArray)
        {
            var work = s;
            if (operators.Contains(work[0]))
            {
                q.Enqueue(work[0].ToString());
                work = work.Substring(1);
            }
            if (operators.Contains(work[work.Length-1]))
            {
                q.Enqueue(work.Substring(0, work.Length - 1));
                q.Enqueue(work[work.Length - 1].ToString());
                continue;
            }
            q.Enqueue(work);
        }

        var res = new List<string>();
        var tmpString = new StringBuilder();
        var lastState = "Op";

        while (q.Count > 0)
        {
            var currElem = q.Dequeue();
            var currState = "St";
            if (unaryOps.Contains(currElem))
                currState = "Un";
            else if (operators.Contains(currElem))
                currState = "Op";

            switch (lastState + currState)
            {
                case "OpUn":
                case "OpSt":
                case "UnUn": // only with + & - unary ops: refinement necessary
                case "UnSt":
                case "StUn": // only with + & - unary ops: refinement necessary
                case "StOp":
                    tmpString.Append(currElem);
                    break;
                case "StSt":
                    res.Add(tmpString.ToString());
                    tmpString.Length=0;
                    tmpString.Append(currElem);
                    break;
                case "OpOp":
                case "UnOp":
                    throw new Exception();
            }
            lastState = currState;
        }

        res.Add(tmpString.ToString());

        return res;
    }

关于c# - 非结构化字符串连接策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25526445/

相关文章:

c# - 基于原生OpenCV的unity上的Android应用

c# - .Net 中的多个 Parallel.ForEach 循环

python - 将两个列表与列表或无值合并的有效方法

c - 一个顶点的 Bellman-ford 算法

c# - 在 C# 中合并 YAML

c# - 使用设置的最大精度格式化十进制数,但没有不需要的尾随零

c# - IEnumerable 集合中元素的序号位置 (Linq to XMl )

algorithm - 检测异常值的最佳方法是什么?

c - 使用哈希函数的高效直方图实现

c++ - Dijkstra 算法中的堆