我发现我的程序正在搜索许多冗长的字符串(20,000+),试图找到一个特定的独特短语。
在C#中执行此操作的最有效方法是什么?
以下是目前的代码:
我已经知道这是一个非常复杂且可能非常无效的算法。 什么是实现相同结果的更好方法?
string result = string.Empty;
for (int i = startPos; i <= response.Length - 1; i++)
{
if (response.Substring(i).StartsWith(startMatchString))
{
string result = response.Substring(i).Substring(11);
for (int j = 0; j <= result.Length - 1; j++)
{
if (result.Substring(j).StartsWith(endMatchString))
{
return result.Remove(j)
}
}
}
}
return result;
答案 0 :(得分:7)
有很多算法,
我建议使用简化的Boyer-Moore,名为Boyer-Moore-Horspool。
C代码出现在维基百科上。 对于java代码,请查看
http://www.fmi.uni-sofia.bg/fmi/logic/vboutchkova/sources/BoyerMoore_java.html
关于这些的好文章可以在下面找到 http://www.ibm.com/developerworks/java/library/j-text-searching.html
如果你想使用内置的东西去正则表达式。
答案 1 :(得分:7)
您可以使用String.IndexOf,但请确保使用StringComparison.Ordinal,否则可能会慢一个数量级。
private string Search2(int startPos, string startMatchString, string endMatchString, string response) {
int startMarch = response.IndexOf(startMatchString, startPos, StringComparison.Ordinal);
if (startMarch != -1) {
startMarch += startMatchString.Length;
int endMatch = response.IndexOf(endMatchString, startMarch, StringComparison.Ordinal);
if (endMatch != -1) { return response.Substring(startMarch, endMatch - startMarch); }
}
return string.Empty;
}
在183 KB文件的大约40%处搜索1000次字符串需要大约270毫秒。没有StringComparison.Ordinal,它花了大约2000毫秒 使用您的方法搜索一次时间超过60秒,因为它在每次迭代时创建一个新字符串(O(n)),使您的方法为O(n ^ 2)。
答案 2 :(得分:6)
这取决于您在字符串中尝试查找的内容。如果您正在寻找特定序列IndexOf/Contains
速度很快,但如果您正在寻找通配符模式Regex
则针对此类搜索进行了优化。
答案 3 :(得分:4)
我会尝试使用正则表达式而不是滚动自己的字符串搜索算法。您可以预编译正则表达式以使其运行得更快。
答案 4 :(得分:0)
你可以使用正则表达式;它针对这种搜索和操作进行了优化。
您也可以尝试IndexOf ...
string result = string.Empty;
if (startPos >= response.Length)
return result;
int startingIndex = response.IndexOf(startMatchString, startPos);
int rightOfStartIndex = startingIndex + startMatchString.Length;
if (startingIndex > -1 && rightOfStartIndex < response.Length)
{
int endingIndex = response.IndexOf(endMatchString, rightOfStartIndex);
if (endingIndex > -1)
result = response.Substring(rightOfStartIndex, endingIndex - rightOfStartIndex);
}
return result;
答案 5 :(得分:0)
对于非常长的字符串,你无法击败boyer-moore搜索算法。它比我在这里解释的要复杂得多,但CodeProject网站上有一篇很好的文章。
答案 6 :(得分:0)
如前所述,正则表达式是你的朋友。 您可能想查看RegularExpressions.Group。 这样,您可以命名匹配结果集的一部分。
答案 7 :(得分:0)
以下是使用IndexOf
的示例(提防:从我的头顶写下,没有测试过):
int skip = 11;
int start = response.IndexOf(startMatchString, startPos);
if (start >= 0)
{
int end = response.IndexOf(startMatchString, start + skip);
if (end >= 0)
return response.Substring(start + skip, end - start - skip);
else
return response.Substring(start + skip);
}
return string.Empty;