更快捷的分裂方式

时间:2017-07-18 15:18:14

标签: c# .net string

我有一个(吨)string(s)这样:

HKR,Drivers,SubClasses,,"wave,midi,mixer,aux"

我基本上希望在strings字符处将其拆分为多个,

但是,如果,字符位于"内或%内,则应忽略该字符。

换句话说,从上面的一行开始,我期待字符串:

HKR
Drivers
SubClasses

"wave,midi,mixer,aux"

(上面一个空行表示一个空字符串)。

如果该行是HKR,Drivers,SubClasses,,%wave,midi,mixer,aux%,那么基本上与上面相同,当然只有最后一个要返回的字符串应为%wave,midi,mixer,aux%

我有一些正常工作的代码,但是 令人难以置信地处理所有行的速度很慢,而且我非常需要找到一种更快的方法来执行此操作。

private static IEnumerable<string> GetValues(string line)
{
    var insideQuotes = false;
    var insidePercent = false;
    var startValueIndex = 0;

    for (var i = 0; i < line.Length; i++)
    {
        if (line[i] == '%' && !insideQuotes)
        {
            insidePercent = !insidePercent;
        }

        if (line[i] == '"')
        {
            insideQuotes = !insideQuotes;
        }

        if (line[i] != ',' || insideQuotes || insidePercent)
        {
            continue;
        }

        yield return line.Substring(startValueIndex, i - startValueIndex);
        startValueIndex = i + 1;
    }
}

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:1)

使用VisualBasic.TextFieldParser并将HasFieldsEnclosedInQuotes设置为true

我会使用像这样的方法一次处理所有行:

public static IEnumerable<string[]> GetValues(string allLines)
{
    using (var parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(new StringReader(allLines)))
    {
        parser.HasFieldsEnclosedInQuotes = true;
        parser.Delimiters = new[] { "," };
        while (!parser.EndOfData)
        {
            string[] nextLineFields = parser.ReadFields();
            yield return nextLineFields;
        }
    }
}

您的样本:

var allLinesFields = GetValues("HKR,Drivers,SubClasses,,\"wave, midi, mixer, aux\"");
foreach (string[] lineFields in allLinesFields)
    Console.WriteLine(string.Join(Environment.NewLine, lineFields));

它将比String.Split更有效,并且还支持您可能甚至没有想过的其他事情。如果格式无效,您还可以处理特殊例外。

答案 1 :(得分:0)

我刚刚重新排序了一些查询语句以避免字符串操作。这应该更有效率。

   private static IEnumerable<string> GetValues2(string line)
    {
        bool insideQuotes = false;
        bool insidePercent = false;
        int startValueIndex = 0;

        for (int i = 0; i < line.Length; i++)
        {
            if (!insideQuotes && line[i] == '%')
            {
                insidePercent = !insidePercent;
            }

            if (line[i] == '"')
            {
                insideQuotes = !insideQuotes;
            }

            if (insideQuotes || insidePercent || line[i] != ',')
            {
                continue;
            }

            yield return line.Substring(startValueIndex, i - startValueIndex);
            startValueIndex = i + 1;
        }
    }