C# 非结构化字符串连接策略
我有一些非结构化字符串数组(长度不同),我希望将它们连接到一个字符串表达式中,以便进行解析。例如:C# 非结构化字符串连接策略,c#,algorithm,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+
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
NB:a、b、c和d用于简洁。它们实际上可以是任意长度的字符串。此外,也可能有任意数量的人。。。不仅仅是4个。
请注意,元素可以具有前导或尾随运算符,这些运算符将确定它是否应连接到数组中的上一个或后续项,以确定它是独立的还是作为下一个表达式的一部分。(一元运算符和确定
a -b => a-b or a, -b
我确实有语法(反语)我当前使用它来确定正在构建的表达式是否格式正确。因此,我连接每个元素,一次一个,解析连接的结果以查看其格式是否正确。如果格式正确,我仍然需要继续使用元素,以防下一个元素有前导运算符。一旦我从解析器(或者数组没有更多的元素),我断定表达式(除了最后2个串联)是有效的,存储它,然后重新开始。(我需要这样做,因为我需要知道有效表达式是数组中特定元素的串联,因为这些元素映射回具有其他信息的对象。)
但这一切都让人觉得有点笨拙
a +b +c +d
a => valid
a +b => valid
a +b +c => valid
a +b +c +d => valid
我会得到4个有效的“信号”,但对于底层表达式,只有最后一个是“真正的”有效“信号”
我想知道是否还有其他更优雅的策略来决定是否应该连接。例如,可能我没有充分使用解析器,或者可能有一些我不熟悉的模式匹配策略
那么我应该如何处理这个问题呢
提前Thx
PS我正在使用C,但我不认为这与此场景相关。似乎如果删除所有空白,所有有效字符串都是奇数。接下来需要检查所有奇数位置是否都是leter(a、b等),偶数位置是否都是有效字符(+、-、等).似乎如果删除所有空白,所有有效字符串都是奇数。接下来需要检查所有奇数位置是否都是LETER(a、b等),偶数位置是否都是有效字符(+、-、等)。这应该起作用,请注意此代码如何处理一元运算符
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;
}
static List GetExpressions(string[]stringArray)
{
常量字符串运算符=“+-*/=”;
常量字符串unaryOps=“+-”;
var q=新队列(stringArray.Length*2);
foreach(stringArray中的字符串s)
{
var功=s;
if(运算符.Contains(工作[0]))
{
q、 排队(工作[0]。ToString());
功=功。子串(1);
}
if(运算符.Contains(工时[work.Length-1]))
{
q、 排队(work.Substring(0,work.Length-1));
q、 排队(工时[work.Length-1].ToString());
持续
}
q、 排队(工作);
}
var res=新列表();
var tmpString=新的StringBuilder();
var lastState=“Op”;
而(q.Count>0)
{
var currElem=q.Dequeue();
var currState=“St”;
if(不包含(currElem))
currState=“Un”;
else if(运算符包含(currElem))
currState=“Op”;
开关(最后状态+当前状态)
{
“OpUn”案:
案例“OpSt”:
案例“UnUn”://仅带+&-一元运算:需要细化
案例“UnSt”:
案例“晕眩”://仅使用+&-一元运算:需要细化
案例“停止”:
tmpString.Append(currElem);
打破
案例“StSt”:
res.Add(tmpString.ToString());
tmpString.Length=0;
tmpString.Append(currElem);
打破
“OpOp”案:
案件“UnOp”:
抛出新异常();
}
lastState=当前状态;
}
res.Add(tmpString.ToString());
返回res;
}
这应该行得通,注意这段代码如何处理一元运算符
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;
}
static List GetExpressions(string[]stringArray)
{
常量字符串运算符=“+-*/=”;
常量字符串unaryOps=“+-”;
var q=新队列(stringArray.Length*2);
foreach(stringArray中的字符串s)
{
var功=s;
if(运算符.Contains(工作[0]))
{
q、 排队(工作[0]。ToString());
功=功。子串(1);
}
if(运算符.Contains(工时[work.Length-1]))
{
q、 排队(work.Substring(0,work.Length-1));
q、 排队(工时[work.Length-1].ToString());
持续
}
q、 排队(工作);
}
var res=新列表();
var tmpString=新的StringBuilder();
var lastState=“Op”;
而(q.Count>0)
{
var currElem=q.Dequeue();
var currState=“St”;
if(不包含(currElem))
currState=“Un”;
else if(运算符包含(currElem))
currState=“Op”;
开关(最后状态+当前状态)
{
“OpUn”案:
案例“OpSt”:
案例“UnUn”://仅带+&-一元运算:需要细化
案例“UnSt”:
案例“晕眩”://仅使用+&-一元运算:需要细化
案例“停止”:
tmpString.Append(currElem);
打破
案例“StS”
public class WaitingForAnyTokenState : State
{
public override State Process(string token)
{
return PushTokenToTokenList(token);
}
protected State PushTokenToTokenList(string token)
{
Tokens.Add(token);
if (operators.Any(op => token.EndsWith(op)))
{
return new WaitingForAnyTokenState() { Expressions = Expressions, Tokens = Tokens };
}
return new WaitingForOperationState() { Expressions = Expressions, Tokens = Tokens };
}
}
public class WaitingForOperationState : State
{
public override State Process(string token)
{
CloseCurrentExpression(token);
return PushTokenToTokenList(token); // let's imagine the same method as above is accessible here
}
private void CloseCurrentExpression(string token)
{
if (!operators.Any(op => token.StartsWith(op)))
{
CombineTokensIntoExpression();
Tokens = new List<string>();
}
}
}
private static void Main(string[] args)
{
var ttea = new TokenToExpressionAggregator();
foreach (var l in new string[] { "a+", "+1", "+c-", "d", "e", "+d", "z+", "a+" }) {
ttea.Add(l);
}
ttea.EndAggregation();
foreach (var expression in ttea.CurrentState.Expressions) {
Console.WriteLine(expression);
}
}
public class TokenToExpressionAggregator
{
public State CurrentState { get; set; }
public TokenToExpressionAggregator()
{
CurrentState = new InitialState();
}
public void Add(string token)
{
CurrentState = CurrentState.Process(token);
}
public void EndAggregation()
{
CurrentState = new FinalState(CurrentState);
}
}
public abstract class State
{
public static string[] operators = new string[] { "+", "-", "*", "/" };
public List<string> Expressions { get; set; }
public List<string> Tokens { get; set; }
public abstract State Process(string token);
protected State PushTokenToTokenList(string token)
{
Tokens.Add(token);
if (operators.Any(op => token.EndsWith(op)))
{
return new WaitingForAnyTokenState() { Expressions = Expressions, Tokens = Tokens };
}
return new WaitingForOperationState() { Expressions = Expressions, Tokens = Tokens };
}
protected void CombineTokensIntoExpression()
{
Expressions.Add(string.Join(" ", Tokens.ToArray()));
}
}
public class InitialState : WaitingForAnyTokenState
{
public InitialState()
{
Expressions = new List<string>();
Tokens = new List<string>();
}
}
public class WaitingForAnyTokenState : State
{
public override State Process(string token)
{
return PushTokenToTokenList(token);
}
}
public class WaitingForOperationState : State
{
public override State Process(string token)
{
CloseCurrentExpression(token);
return PushTokenToTokenList(token);
}
private void CloseCurrentExpression(string token)
{
if (!operators.Any(op => token.StartsWith(op)))
{
CombineTokensIntoExpression();
Tokens = new List<string>();
}
}
}
public class FinalState : State
{
public FinalState(State state)
{
Expressions = state.Expressions;
Tokens = state.Tokens;
CombineTokensIntoExpression();
Tokens = null;
}
public override State Process(string token)
{
return this;
}
}