C# 如何简化此方法(拆分不带引号、不带括号、不带换行符的逗号)?
好奇这是否可以简化C# 如何简化此方法(拆分不带引号、不带括号、不带换行符的逗号)?,c#,parsing,C#,Parsing,好奇这是否可以简化 internal static IEnumerable<string> Split(string str, char sep = ',') { int lastIndex = 0; bool quoted = false; bool escaped = false; bool bracketed = false; char lastQuote = '\0'; for (int i = 0; i < str.L
internal static IEnumerable<string> Split(string str, char sep = ',')
{
int lastIndex = 0;
bool quoted = false;
bool escaped = false;
bool bracketed = false;
char lastQuote = '\0';
for (int i = 0; i < str.Length; ++i)
{
if (str[i] == '[')
{
if (!quoted && !escaped)
bracketed = true;
escaped = false;
}
else if (str[i] == ']')
{
if (!quoted && !escaped)
bracketed = false;
escaped = false;
}
else if (str[i] == '\\')
{
escaped = !escaped;
}
else if (str[i] == '"' || str[i] == '\'')
{
if (!escaped)
{
if (quoted)
{
if (lastQuote == str[i])
quoted = false;
}
else
{
quoted = true;
lastQuote = str[i];
}
}
escaped = false;
}
else if (str[i] == sep)
{
if (!quoted && !escaped && !bracketed)
{
yield return str.Substring(lastIndex, i - lastIndex);
lastIndex = i + 1;
}
escaped = false;
}
else
{
escaped = false;
}
}
yield return str.Substring(lastIndex);
}
预期产出:
"comma, in quotes"
comma[in,brackets]
comma[in "quotes, and brackets"]
"woah, 'nelly,' \"now you,re [talking, crazy\""
要保持你的自动机状态有点尴尬。在这种情况下,我将使用单个变量或堆栈。因此,您当前的状态始终为stateStack.Peek。容易阅读。易于处理嵌套状态 编辑:这里有一个简单的例子。我相信您可以扩展它来添加错误处理和规则的细节
enum ParserState
{
Text,
Bracketed,
Quoted,
EscapChar,
}
internal static IEnumerable<string> Split(string str, char sep)
{
int lastIdx = 0;
char c;
ParserState s;
Stack<ParserState> state = new Stack<ParserState>();
state.Push(ParserState.Text);
for (int i = 0; i < str.Length; i++)
{
c = str[i];
s = state.Peek();
if (s == ParserState.EscapChar
|| (s == ParserState.Bracketed && c == ']')
|| (s == ParserState.Quoted && c == '"'))
{
state.Pop();
}
else if (c == '[')
state.Push(ParserState.Bracketed);
else if (c == '"')
state.Push(ParserState.Quoted);
else if (c == '\\')
state.Push(ParserState.EscapChar);
else if (s == ParserState.Text && c == sep)
{
yield return str.Substring(lastIdx, i - lastIdx);
lastIdx = i + 1;
}
}
yield return str.Substring(lastIdx);
}
要保持你的自动机状态有点尴尬。在这种情况下,我将使用单个变量或堆栈。因此,您当前的状态始终为stateStack.Peek。容易阅读。易于处理嵌套状态 编辑:这里有一个简单的例子。我相信您可以扩展它来添加错误处理和规则的细节
enum ParserState
{
Text,
Bracketed,
Quoted,
EscapChar,
}
internal static IEnumerable<string> Split(string str, char sep)
{
int lastIdx = 0;
char c;
ParserState s;
Stack<ParserState> state = new Stack<ParserState>();
state.Push(ParserState.Text);
for (int i = 0; i < str.Length; i++)
{
c = str[i];
s = state.Peek();
if (s == ParserState.EscapChar
|| (s == ParserState.Bracketed && c == ']')
|| (s == ParserState.Quoted && c == '"'))
{
state.Pop();
}
else if (c == '[')
state.Push(ParserState.Bracketed);
else if (c == '"')
state.Push(ParserState.Quoted);
else if (c == '\\')
state.Push(ParserState.EscapChar);
else if (s == ParserState.Text && c == sep)
{
yield return str.Substring(lastIdx, i - lastIdx);
lastIdx = i + 1;
}
}
yield return str.Substring(lastIdx);
}
您是否考虑过regex?您所生成的代码可能不是最简洁或最优雅的,但它是可维护的——在我看来,这是代码最重要的一点。此代码是否导致任何问题?如果不是的话,我就不去管它了。@Jimplade:是的,我相信这将是一个可怕的方法,如果它是可行的话@克丽丝芙:在我的测试中似乎很有效。我不太担心优化它,只是想知道它是否可以进一步简化。。。它有一些代码冗余之类的问题。@jimplate:因为它不容易读、写和维护?是的,这是一个糟糕的方法。我也不知道如何在几个正则表达式中实现这一点。。除非你想用正则表达式替换掉不相关的部分,然后在剩下的部分做一个简单的字符串分割,但是。。。我看不出这有多好。jimplode:我很想看到一个执行此任务的正则表达式!无论如何,发布一个,我会投票赞成。你有没有考虑过regex?你所产生的代码,虽然可能不是最简洁或优雅的,但它是可维护的——在我看来,这是代码最重要的一点。此代码是否导致任何问题?如果不是的话,我就不去管它了。@Jimplade:是的,我相信这将是一个可怕的方法,如果它是可行的话@克丽丝芙:在我的测试中似乎很有效。我不太担心优化它,只是想知道它是否可以进一步简化。。。它有一些代码冗余之类的问题。@jimplate:因为它不容易读、写和维护?是的,这是一个糟糕的方法。我也不知道如何在几个正则表达式中实现这一点。。除非你想用正则表达式替换掉不相关的部分,然后在剩下的部分做一个简单的字符串分割,但是。。。我看不出这有多好。jimplode:我很想看到一个执行此任务的正则表达式!无论如何,发布一个,我会投票支持。然后把引号和[s]都推到上面?关于转义符呢?你会把它们推到上面吗?好吧,这对你来说更像是一个问题。你支持嵌套括号吗?如果支持,那么每次遇到['。如果没有,则推第一个字符,并将其他字符视为纯文本。括号和引号的组合也是如此。至于转义字符-是的,我会推这些字符。基本上你想要状态。Peek就是我现在所在的位置。因此,如果你遇到转义字符,那么你接下来的循环过程需要知道它。我也是一位同事nfused:您没有在输出上取消转义符?这是疏忽还是有意的?嗯…不确定…实际上还没有需要在实践中取消任何转义。我不知道这个方法是否应该处理取消转义,或者应该委托给实际使用此函数的方法。反正都是内部的。Peeo,Pop,Push,Subst戒指。它有点吸引人:把引号和[s]都推到上面?关于转义符呢?你会把它们也推到上面吗?好吧,这对你来说更是个问题。你支持嵌套括号吗?如果支持,那么每次遇到['。如果没有,则推第一个字符,并将其他字符视为纯文本。括号和引号的组合也是如此。至于转义字符-是的,我会推这些字符。基本上你想要状态。Peek就是我现在所在的位置。因此,如果你遇到转义字符,那么你接下来的循环过程需要知道它。我也是一位同事nfused:您没有在输出上取消转义符?这是疏忽还是有意的?嗯…不确定…实际上还没有需要在实践中取消任何转义。我不知道这个方法是否应该处理取消转义,或者应该委托给实际使用此函数的方法。反正都是内部的。Peeo,Pop,Push,Subst戒指。有点吸引人: