我正在编写一个应用程序,该应用程序旨在以以下格式处理数千篇包含大量spintax的文章/条目:

{Hello|Hi} {World|There!}, how are you?

但是,当我使用profiler运行应用程序时,我注意到处理regex的部分占用了大量资源,我的应用程序最终由于内存不足而崩溃。有谁能建议一种改进我的代码或者更好的解析spintax的方法吗?
public static String Spin(String text)
{
        Regex reg = new Regex(@"\{[^\{\}]*\}");
        Random rand = new Random((int)DateTime.Now.Ticks);
        while (true)
        {
            Match m = reg.Match(text);
            if (!m.Success) break;
            String[] parts = m.Value.TrimStart('{').TrimEnd('}').Split('|');
            int i = rand.Next(parts.Length);
            text = text.Substring(0, m.Index) + parts[i] + text.Substring(m.Index + m.Length);
        }
        return text;
  }

最佳答案

我已经实现了我的快速版本(noRegex、noSplit、noSubstring、noReplace和其他字符串操作方法)。要复制字符串,我正在使用String.CopyTo将符号复制到一个普通的char数组。
此代码完全支持嵌套的spintax(可能无限深度)。一个限制是每个税的最大选择数,目前是100,但可以改为1000个或更多。另一个限制是输入字符串的最大长度,现在是100000,但也可以增加。
关于性能-我的测试表明,这段代码比任何优化的regex解决方案(包括jim mischel的解决方案)快15倍,比使用子字符串和其他字符串操作方法的版本快5倍。我已经在VS2012的发布模式下用优化代码设置测试过了。

    static int[] partIndices = new int[100];
    static int[] depth = new int[100];
    static char[] symbolsOfTextProcessed = new char[100000];

    public static String SpinEvenMoreFaster(String text)
    {
        int cur = SpinEvenMoreFasterInner(text, 0, text.Length, 0);
        return new String(symbolsOfTextProcessed, 0, cur);
    }

    public static int SpinEvenMoreFasterInner(String text, int start, int end, int symbolIndex)
    {
        int last = start;
        for (int i = start; i < end; i++)
        {
            if (text[i] == '{')
            {
                int k = 1;
                int j = i + 1;
                int index = 0;
                partIndices[0] = i;
                depth[0] = 1;
                for (; j < end && k > 0; j++)
                {
                    if (text[j] == '{')
                        k++;
                    else if (text[j] == '}')
                        k--;
                    else if (text[j] == '|')
                    {
                        if (k == 1)
                        {
                            partIndices[++index] = j;
                            depth[index] = 1;
                        }
                        else
                            depth[index] = k;
                    }
                }
                if (k == 0)
                {
                    partIndices[++index] = j - 1;
                    int part = rand.Next(index);
                    text.CopyTo(last, symbolsOfTextProcessed, symbolIndex, i - last);
                    symbolIndex += i - last;
                    if (depth[part] == 1)
                    {
                        text.CopyTo(partIndices[part] + 1, symbolsOfTextProcessed, symbolIndex, partIndices[part + 1] - partIndices[part] - 1);
                        symbolIndex += partIndices[part + 1] - partIndices[part] - 1;
                    }
                    else
                    {
                        symbolIndex = SpinEvenMoreFasterInner(text, partIndices[part] + 1, partIndices[part + 1], symbolIndex);
                    }
                    i = j - 1;
                    last = j;
                }
            }
        }
        text.CopyTo(last, symbolsOfTextProcessed, symbolIndex, end - last);
        return symbolIndex + end - last;
    }

07-24 22:32