C# 在两根弦之间

C# 在两根弦之间,c#,.net,optimization,string,C#,.net,Optimization,String,我在C#中有一个简单的方法: 如何对此进行优化?您可以构建一个正则表达式: var regex = strFirst + "(.*)" + strLast; 您的中间文本将是匹配的第一个(也是唯一一个)捕获。使用正则表达式怎么样?这可能比构建临时字符串要快。 此外,这将使您能够轻松、温和地处理找不到此类字符串的情况。如果我已经了解您想要做什么,我认为您的实现可能不正确 这是一个我认为至少在GC方面性能更好的实现,因为它不使用对SubString的多个调用,这些调用会在堆上创建新字符串,而这些字

我在C#中有一个简单的方法:


如何对此进行优化?

您可以构建一个正则表达式:

var regex = strFirst + "(.*)" + strLast;

您的中间文本将是匹配的第一个(也是唯一一个)捕获。

使用正则表达式怎么样?这可能比构建临时字符串要快。
此外,这将使您能够轻松、温和地处理找不到此类字符串的情况。

如果我已经了解您想要做什么,我认为您的实现可能不正确

这是一个我认为至少在GC方面性能更好的实现,因为它不使用对
SubString
的多个调用,这些调用会在堆上创建新字符串,而这些字符串只是临时使用

public static string BetweenOfFixed(string ActualStr, string StrFirst, string StrLast)
{
  int startIndex = ActualStr.IndexOf(StrFirst) + StrFirst.Length;
  int endIndex = ActualStr.IndexOf(StrLast, startIndex);
  return ActualStr.Substring(startIndex, endIndex - startIndex);
}
比较此解决方案与正则表达式解决方案的性能会很有趣。

下面是代码如何与正则表达式测试进行比较:

void Main()
{
    string input = "abcdefghijklmnopq";
    string first = "de";
    string last = "op";
    Regex re1 = new Regex("de(.*)op", RegexOptions.None);
    Regex re2 = new Regex("de(.*)op", RegexOptions.Compiled);

    // pass 1 is JIT preheat
    for (int pass = 1; pass <= 2; pass++)
    {
        int iterations = 1000000;
        if (pass == 1)
            iterations = 1;

        Stopwatch sw = Stopwatch.StartNew();
        for (int index = 0; index < iterations; index++)
            BetweenOfFixed(input, first, last);
        sw.Stop();
        if (pass == 2)
            Debug.WriteLine("IndexOf: " + 
                sw.ElapsedMilliseconds + "ms");

        sw = Stopwatch.StartNew();
        for (int index = 0; index < iterations; index++)
            BetweenOfRegexAdhoc(input, first, last);
        sw.Stop();
        if (pass == 2)
            Debug.WriteLine("Regex adhoc: " + 
                sw.ElapsedMilliseconds + "ms");

        sw = Stopwatch.StartNew();
        for (int index = 0; index < iterations; index++)
            BetweenOfRegexCached(input, first, last);
        sw.Stop();
        if (pass == 2)
            Debug.WriteLine("Regex uncompiled: " +
                sw.ElapsedMilliseconds + "ms");

        sw = Stopwatch.StartNew();
        for (int index = 0; index < iterations; index++)
            BetweenOfRegexCompiled(input, first, last);
        sw.Stop();
        if (pass == 2)
            Debug.WriteLine("Regex compiled: " +
                sw.ElapsedMilliseconds + "ms");
    }
}

public static string BetweenOfFixed(string ActualStr, string StrFirst,
    string StrLast)
{
    int startIndex = ActualStr.IndexOf(StrFirst) + StrFirst.Length;
    int endIndex = ActualStr.IndexOf(StrLast, startIndex);
    return ActualStr.Substring(startIndex, endIndex - startIndex);
}

public static string BetweenOfRegexAdhoc(string ActualStr, string StrFirst,
    string StrLast)
{
    // I'm assuming you don't replace the delimiters on every call
    Regex re = new Regex("de(.*)op", RegexOptions.None);
    return re.Match(ActualStr).Groups[1].Value;
}

private static Regex _BetweenOfRegexCached =
    new Regex("de(.*)op", RegexOptions.None);
public static string BetweenOfRegexCached(string ActualStr, string StrFirst,
    string StrLast)
{
    return _BetweenOfRegexCached.Match(ActualStr).Groups[1].Value;
}

private static Regex _BetweenOfRegexCompiled =
    new Regex("de(.*)op", RegexOptions.Compiled);
public static string BetweenOfRegexCompiled(string ActualStr, string StrFirst,
    string StrLast)
{
    return _BetweenOfRegexCompiled.Match(ActualStr).Groups[1].Value;
}
void Main()
{
字符串输入=“abcdefghijklmnopq”;
string first=“de”;
字符串last=“op”;
正则表达式re1=新正则表达式(“de(.*)op”,RegexOptions.None);
正则表达式re2=新正则表达式(“de(.*)op”,RegexOptions.Compiled);
//通过1是JIT预热

对于(int pass=1;pass我想仔细的代码分析会告诉您,这个方法实际上是应用程序性能的瓶颈?相关:如果我调用它100000次,这个方法会非常慢,所以建议一个替代逻辑,以获得与这个函数中表示的相同的输出。@Rahul:为什么要调用这个方法100000次?我不是说独立地对方法进行基准测试;我是说对实际的应用程序代码进行评测。哦,对了,是因为“我认为这太慢了,所以我要运行大量次,并对其进行基准测试以证明它!”你肯定想在那些字符串上使用
Regex.Escape
。@Kobi:你能告诉我如何删除转义序列吗,因为我是通过替换(“\n”,”).Replace(“\0”,”).Replace(“\\”,”)等等。谢谢!!但是你能告诉我为什么要声明startIndex,endIndex如果它们没有用的话两者都用,endIndex一次,startIndex两次。@Rahul,正如@Simon所说,两者都用。在最后的子字符串中,我使用startIndex作为字符串的偏移量,然后使用endIndex-startIndex来获取要从字符串中提取的字符数字符串,这给出了strFirst和strLast之间的字符串部分。我将代码与regex进行了比较,我将把它作为CW的答案发布,因为我没有任何要添加到您的代码中。这里:您是否根据
Debug.WriteLine
语句以发布代码的形式运行了build this?我想您可能已经在IDE中以调试版本的形式运行了它。我您的代码并更改为
Console.WriteLine
并进行了发布构建。从控制台窗口运行时,我得到了以下结果399ms、9083ms、1258ms、806ms。我在Framework 4.0上进行了测试。
void Main()
{
    string input = "abcdefghijklmnopq";
    string first = "de";
    string last = "op";
    Regex re1 = new Regex("de(.*)op", RegexOptions.None);
    Regex re2 = new Regex("de(.*)op", RegexOptions.Compiled);

    // pass 1 is JIT preheat
    for (int pass = 1; pass <= 2; pass++)
    {
        int iterations = 1000000;
        if (pass == 1)
            iterations = 1;

        Stopwatch sw = Stopwatch.StartNew();
        for (int index = 0; index < iterations; index++)
            BetweenOfFixed(input, first, last);
        sw.Stop();
        if (pass == 2)
            Debug.WriteLine("IndexOf: " + 
                sw.ElapsedMilliseconds + "ms");

        sw = Stopwatch.StartNew();
        for (int index = 0; index < iterations; index++)
            BetweenOfRegexAdhoc(input, first, last);
        sw.Stop();
        if (pass == 2)
            Debug.WriteLine("Regex adhoc: " + 
                sw.ElapsedMilliseconds + "ms");

        sw = Stopwatch.StartNew();
        for (int index = 0; index < iterations; index++)
            BetweenOfRegexCached(input, first, last);
        sw.Stop();
        if (pass == 2)
            Debug.WriteLine("Regex uncompiled: " +
                sw.ElapsedMilliseconds + "ms");

        sw = Stopwatch.StartNew();
        for (int index = 0; index < iterations; index++)
            BetweenOfRegexCompiled(input, first, last);
        sw.Stop();
        if (pass == 2)
            Debug.WriteLine("Regex compiled: " +
                sw.ElapsedMilliseconds + "ms");
    }
}

public static string BetweenOfFixed(string ActualStr, string StrFirst,
    string StrLast)
{
    int startIndex = ActualStr.IndexOf(StrFirst) + StrFirst.Length;
    int endIndex = ActualStr.IndexOf(StrLast, startIndex);
    return ActualStr.Substring(startIndex, endIndex - startIndex);
}

public static string BetweenOfRegexAdhoc(string ActualStr, string StrFirst,
    string StrLast)
{
    // I'm assuming you don't replace the delimiters on every call
    Regex re = new Regex("de(.*)op", RegexOptions.None);
    return re.Match(ActualStr).Groups[1].Value;
}

private static Regex _BetweenOfRegexCached =
    new Regex("de(.*)op", RegexOptions.None);
public static string BetweenOfRegexCached(string ActualStr, string StrFirst,
    string StrLast)
{
    return _BetweenOfRegexCached.Match(ActualStr).Groups[1].Value;
}

private static Regex _BetweenOfRegexCompiled =
    new Regex("de(.*)op", RegexOptions.Compiled);
public static string BetweenOfRegexCompiled(string ActualStr, string StrFirst,
    string StrLast)
{
    return _BetweenOfRegexCompiled.Match(ActualStr).Groups[1].Value;
}
IndexOf: 1419ms Regex adhoc: 7788ms Regex uncompiled: 1074ms Regex compiled: 682ms