我知道这里已经讨论了类似的问题和问题,但不完全是我需要的问题。
让我们面对这个问题,我们有一根长绳子,一根很长的绳子,大海捞针,还有一根针。经典问题:搜索出现的所有内容。好Regex.Matches
是一个很好的函数,它只有一个问题,在我们的例子中是一个严重的问题,它不计算重叠的字符串。
例如
string haystack = "(anything)....bbb....(anything)";
string needle = "bb"; //must be a string not a char
现在我们看到,bb
在干草堆的bbb
部分中是2倍。 (BBb
和bBB
)Regex.Matches
只找到第一个,并从第三个b
进一步搜索。并且不会找到任何其他。
任何想法如何在长草垛字符串中搜索具有重叠选项的毛发子串(当然必须有效)?
谢谢,如果重复,请抱歉。
答案 0 :(得分:3)
在循环中使用string.IndexOf
string haystack = "(anything)....bbb....(anything)";
string needle = "bb";
int pos = 0;
while((pos = haystack.IndexOf(needle, pos)) != -1)
{
Console.Write("Found at pos:" + pos.ToString());
Console.WriteLine(" - " + haystack.Substring(pos, needle.Length));
pos++;
}
答案 1 :(得分:1)
为什么不只是维护指向子串的位置的指针,然后每当找到匹配时从该位置+ 1恢复你的Regex.Matches。
答案 2 :(得分:1)
更简单的解决方案是在其他人建议的循环中使用string.IndexOf
,但是......如果你真的想使用正则表达式,你可以使用积极的先行来处理重叠。例如:
string test = "(anything)....bbb....(anything)";
Regex r = new Regex("b(?=b)");
foreach (Match m in r.Matches(test))
{
Console.WriteLine(string.Format("match at: {0}",m.Index));
}
将在14
和15
两个索引处匹配。
对于2个字符的匹配,这是可以管理的,但是如果匹配时间较长,可能会变得很痛苦。
确定这个在实践中是否比循环解决方案中的string.IndexOf
更快
编辑:因为我的好奇心越来越好,我不得不试着找出哪一个实际上更快,这里有一些测试代码:
http://dotnetfiddle.net/qneK5u
string test = "(anything)....bbbbbb....(anything)";
Regex r = new Regex("b(?=b)");
var s = new System.Diagnostics.Stopwatch();
s.Start();
int i=0;
int l=5000;
for (;i<l;i++) {
var result = r.Matches(test);
}
Console.WriteLine(s.ElapsedTicks.ToString());
i = 0;
string needle = "bb";
int pos = 0;
s.Reset();
s.Start();
for (;i<l;i++) {
pos = 0;
while((pos = test.IndexOf(needle, pos)) != -1)
{
pos++;
}
}
Console.WriteLine(s.ElapsedTicks.ToString());
正则表达式解决方案的出现速度明显加快,但我不确定我是否正在进行公平的测试。
答案 3 :(得分:0)
此函数返回起始匹配针字符串的索引列表(可能比正则表达式更快):
public static List<int> GetPositions(string haystack , string needle)
{
List<int> ret = new List<int>();
if (string.IsNullOrEmpty(haystack) || string.IsNullOrEmpty(needle))
return ret;
for(int i=0;i<haystack.Length-needle.Length+1;i++)
{
int j = 0;
for(;j<needle.Length && haystack[i+j]==needle[j];j++);
if(j==needle.Length )
ret.Add(i);
}
return ret;
}