Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/jenkins/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
(C#)提高定制getBetweenAll的速度_C#_String_Performance_Indexof - Fatal编程技术网

(C#)提高定制getBetweenAll的速度

(C#)提高定制getBetweenAll的速度,c#,string,performance,indexof,C#,String,Performance,Indexof,我用c#编写了一个自定义扩展方法,这是对extensionmethod string[]getBetweenAll(string source、string startstring、string endstring)的改进 最初,此extensionmethod发现两个字符串之间的所有子字符串,例如: string source = "<1><2><3><4>"; source.getBetweenAll("<", ">"); //ou

我用c#编写了一个自定义扩展方法,这是对extensionmethod string[]getBetweenAll(string source、string startstring、string endstring)的改进

最初,此extensionmethod发现两个字符串之间的所有子字符串,例如:

string source = "<1><2><3><4>";
source.getBetweenAll("<", ">");
//output: string[] {"1", "2", "3", "4"}
string source=”“;
source.getBetweenAll(“”);
//输出:字符串[]{“1”、“2”、“3”、“4”}
但是如果在开始时出现另一个<,它将介于这和整个字符串之间

string source = "<<1><2><3><4>";
source.getBetweenAll("<", ">");
//output: string[] {"<1><2><3><4"}

string source=”“为了找到第一个出现的“我写了一个简单的方法,比你的方法快四倍(但到目前为止没有
preserve
参数):


使用堆栈进行操作。一旦看到开始标记,就开始向添加字符。一旦看到结束标记,就从堆栈中弹出所有内容,这将是您感兴趣的字符

现在,一旦实现了基本大小写,就可以使用递归来改进它。如果在结束标记之前看到另一个开始标记,则开始将字符收集到新堆栈中,直到看到结束标记为止

这将给您带来O(N)的复杂性,因为您只需要传递一次所有内容


如果在开始标记之前看到结束标记,您还需要处理该情况,但您的问题不清楚程序应该执行什么操作。

我发现这正是我想要的,但另一方面!一个执行先前Indexof(字符串源、字符串标记、int偏移量)的函数对于其他的东西,我们仍然非常感激

public static List<string> GetBetweenAll(this string main, string start, string finish, bool preserve = false,  int index = 0)
{
    List<string> matches = new List<string>();
    Match gbMatch = new Regex(Regex.Escape(start) + "(.+?)" + Regex.Escape(finish)).Match(main, index);
    while (gbMatch.Success)
    {
        matches.Add((preserve ? start : string.Empty) + gbMatch.Groups[1].Value + (preserve ? finish : string.Empty));
        gbMatch = gbMatch.NextMatch();
    }
    return matches;
}
public static string[] getBetweenAllBackwards(this string main, string strstart, string strend, bool preserve = false)
{
    List<string> all = Reverse(main).GetBetweenAll(Reverse(strend), Reverse(strstart), preserve);
    for (int i = 0; i < all.Count; i++)
    {
        all[i] = Reverse(all[i]);
    }
    return all.ToArray();
}
public static string Reverse(string s)
{
    char[] charArray = s.ToCharArray();
    Array.Reverse(charArray);
    return new string(charArray);
}
publicstaticlist GetBetweenAll(此字符串主要、字符串开始、字符串结束、boolpreserve=false、int索引=0)
{
列表匹配项=新列表();
Match gbMatch=newregex(Regex.Escape(start)+“(.+?)”+Regex.Escape(finish)).Match(main,index);
while(gbMatch.Success)
{
matches.Add((preserve?start:string.Empty)+gbMatch.Groups[1]。Value+(preserve?finish:string.Empty));
gbMatch=gbMatch.NextMatch();
}
返回比赛;
}
公共静态字符串[]getBetweenAllBackwards(此字符串main、字符串strstart、字符串streng、bool preserve=false)
{
列出全部=反向(主)。GetBetweenAll(反向(强度)、反向(strstart)、保留);
for(int i=0;i
作为原始的GetBetweenAll,我们可以使用正则表达式。为了只匹配封闭字符串的最短“内部”外观,我们必须对开始字符串使用负前瞻,对内容使用非贪婪量词

public static string[] getBetweenAll(this string main, 
    string strstart, string strend, bool preserve = false)
{
    List<string> results = new List<string>();

    string regularExpressionString = string.Format("{0}(((?!{0}).)+?){1}", 
        Regex.Escape(strstart), Regex.Escape(strend));
    Regex regularExpression = new Regex(regularExpressionString, RegexOptions.IgnoreCase);

    var matches = regularExpression.Matches(main);

    foreach (Match match in matches)
    {
        if (preserve)
        {
            results.Add(match.Value);
        }
        else
        {
            results.Add(match.Groups[1].Value);
        }
    }

    return results.ToArray();
}
public静态字符串[]getBetweenAll(此字符串主,
字符串strstart、字符串strengd、bool preserve=false)
{
列表结果=新列表();
string regularExpressionString=string.Format(“{0}(((?!{0})。)+?){1}”,
正则表达式Escape(strstart),正则表达式Escape(strengd));
Regex regularpression=newregex(regularpressionstring,RegexOptions.IgnoreCase);
var matches=regularExpression.matches(main);
foreach(匹配中的匹配)
{
如果(保留)
{
结果。添加(匹配。值);
}
其他的
{
结果.Add(match.Groups[1].Value);
}
}
返回结果。ToArray();
}

是的,但这很有趣!使用编译的正则表达式(例如,
]*)>
)可以加快速度吗?什么对您来说比较慢,您希望什么结果是可以的?这里是微优化人员!您可以尝试将
结束
更改为数组,并使用
对其进行迭代(int i=0等
,并将预期的
结果
的最大大小传递给
结果
的列表构造函数。有什么原因不使用正则表达式吗?没有,它速度更快,但在我尝试抓取内容时会打印出奇怪的结果。它应该在末尾进行搜索,比如说“.mp4直到它第一次出现“http://”,以避免从整个字符串的开头以及字符串之间的所有内容变成“http://”。这确实很难解释,但我希望您understand@Ragnar然后展示一些实际的输入和输出示例。问题是,它需要从“>”的每次出现开始反向执行这不会改变任何事情-现在您的开始标记是“>”,您可以从字符串的末尾转到开头。您应该给出用于实际测试的文本,并明确您的期望值。这与您在问题中的解释一致。
public static string[] getBetweenAll2(this string main, string strstart, string strend, bool preserve = false)
{
    List<string> results = new List<string>();

    int lenStart = strstart.Length; 
    int lenEnd = strend.Length;

    int index = 0;

    Stack<int> starPos = new Stack<int>();

    while (true)
    {
        int indexStart = main.IndexOf(strstart, index);
        int indexEnd = main.IndexOf(strend, index);

        if (indexStart != -1 && indexStart < indexEnd)
        {
            index = indexStart + lenStart;
            starPos.Push(index);
        }
        else if (indexEnd != -1 && (indexEnd < indexStart || indexStart == -1))
        {
            if (starPos.Count == 1)
            {
                int startOfInterst = starPos.Pop();
                results.Add(main.Substring(startOfInterst, indexEnd - startOfInterst));
            } else if(starPos.Count>0)
            {
                starPos.Pop();
            }
            index = indexEnd + lenEnd;
        }
        else
        {
            break;
        }
    }
    return results.ToArray();
}
public static List<string> GetBetweenAll(this string main, string start, string finish, bool preserve = false,  int index = 0)
{
    List<string> matches = new List<string>();
    Match gbMatch = new Regex(Regex.Escape(start) + "(.+?)" + Regex.Escape(finish)).Match(main, index);
    while (gbMatch.Success)
    {
        matches.Add((preserve ? start : string.Empty) + gbMatch.Groups[1].Value + (preserve ? finish : string.Empty));
        gbMatch = gbMatch.NextMatch();
    }
    return matches;
}
public static string[] getBetweenAllBackwards(this string main, string strstart, string strend, bool preserve = false)
{
    List<string> all = Reverse(main).GetBetweenAll(Reverse(strend), Reverse(strstart), preserve);
    for (int i = 0; i < all.Count; i++)
    {
        all[i] = Reverse(all[i]);
    }
    return all.ToArray();
}
public static string Reverse(string s)
{
    char[] charArray = s.ToCharArray();
    Array.Reverse(charArray);
    return new string(charArray);
}
public static string[] getBetweenAll(this string main, 
    string strstart, string strend, bool preserve = false)
{
    List<string> results = new List<string>();

    string regularExpressionString = string.Format("{0}(((?!{0}).)+?){1}", 
        Regex.Escape(strstart), Regex.Escape(strend));
    Regex regularExpression = new Regex(regularExpressionString, RegexOptions.IgnoreCase);

    var matches = regularExpression.Matches(main);

    foreach (Match match in matches)
    {
        if (preserve)
        {
            results.Add(match.Value);
        }
        else
        {
            results.Add(match.Groups[1].Value);
        }
    }

    return results.ToArray();
}