(C#)提高定制getBetweenAll的速度
我用c#编写了一个自定义扩展方法,这是对extensionmethod string[]getBetweenAll(string source、string startstring、string endstring)的改进 最初,此extensionmethod发现两个字符串之间的所有子字符串,例如:(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
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();
}