gpt4 book ai didi

c# - 使用有限状态机解析 CSV 数据

转载 作者:太空宇宙 更新时间:2023-11-03 10:42:29 24 4
gpt4 key购买 nike

我想读取一个包含逗号分隔值的文件,所以写了一个有限状态机:

private IList<string> Split(string line)
{
List<string> values = new List<string>();
string value = string.Empty;
ParseState state = ParseState.Initial;
foreach (char c in line)
{
switch (state)
{
case ParseState.Initial:
switch (c)
{
case COMMA:
values.Add(string.Empty);
break;
case QUOTE:
state = ParseState.Quote;
break;
default:
value += c;
state = ParseState.Data;
break;
}
break;
case ParseState.Data:
switch (c)
{
case COMMA:
values.Add(value);
value = string.Empty;
state = ParseState.Initial;
break;
case QUOTE:
throw new InvalidDataException("Improper quotes");
default:
value += c;
break;
}
break;
case ParseState.Quote:
switch (c)
{
case QUOTE:
state = ParseState.QuoteInQuote;
break;
default:
value += c;
break;
}
break;
case ParseState.QuoteInQuote:
switch (c)
{
case COMMA:
values.Add(value);
value = string.Empty;
state = ParseState.Initial;
break;
case QUOTE:
value += c;
state = ParseState.Quote;
break;
default:
throw new InvalidDataException("Unpaired quotes");
}
break;
}
}

switch (state)
{
case ParseState.Initial:
case ParseState.Data:
case ParseState.QuoteInQuote:
values.Add(value);
break;
case ParseState.Quote:
throw new InvalidDataException("Unclosed quotes");
}

return values;
}

是的,我知道关于 CSV 解析器的建议是“不要自己编写”,但是

  1. 我很快就需要它
  2. 我们的工作下载政策需要几天时间才能让我从“网络”中获取开源。

嘿,至少我没有从 string.Split() 开始,或者更糟的是,尝试使用 Regex!

是的,我知道它可以通过使用 StringBuilder 来改进,并且它对数据中的引号有限制,但是

  1. 性能不是问题并且
  2. 这只是为了在内部生成明确定义的测试数据,

所以我不关心那些。

关心的是末尾明显的尾随 block ,用于清除最后一个逗号后的所有数据,以及它开始看起来像某种反模式的方式在那里,这正是像 FSM 这样的“好”模式应该避免的事情。

所以我的问题是:最后这个 block 是不是某种反模式,它会不会在未来反噬我?

最佳答案

我见过的所有 FSM(不是我去寻找它们,请注意)都有某种“清理”步骤,这仅仅是由于枚举的性质。

在 FSM 中,您总是根据当前状态进行操作,然后为下一次迭代重置“当前状态”,因此一旦您到达迭代末尾,您必须执行最后一个操作来进行操作“当前状态”。 (最好将其视为作用于“先前状态”并设置“当前状态”)。

因此,我认为您所做的是模式的一部分

但是您为什么不尝试 SO 上的其他一些答案呢?

适应的解决方案,仍然是 FSM:

public IEnumerable<string> fsm(string s)
{
int i, a = 0, l = s.Length;
var q = true;
for (i = 0; i < l; i++)
{
switch (s[i])
{
case ',':
if (q)
{
yield return s.Substring(a, i - a).Trim();
a = i + 1;
}
break;

// pick your flavor
case '"':
//case '\'':
q = !q;
break;
}
}
yield return s.Substring(a).Trim();
}

// === usage ===
var row = fsm(csvLine).ToList();
foreach(var column in fsm(csvLine)) { ... }

关于c# - 使用有限状态机解析 CSV 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24839096/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com