C# StringBuilder中最快的搜索方法
我有一个名为C# StringBuilder中最快的搜索方法,c#,.net,vb.net,performance,stringbuilder,C#,.net,Vb.net,Performance,Stringbuilder,我有一个名为stb\u Swap\u Tabu的StringBuilder用于存储课程名称, 我正在使用以下方法查找课程: stb_Swap_Tabu.ToString.Contains("CourseName") 就我而言,性能是最重要的问题。 有没有更快的方法?StringBuilder并不是真的用于所有字符串目的。如果您真的需要搜索一个,您必须编写自己的方法 有几种适合不同情况的字符串搜索算法 下面是Knuth–Morris–Pratt算法的一个简单实现,该算法只关心顺序匹配(没有大小写
stb\u Swap\u Tabu的StringBuilder
用于存储课程名称,
我正在使用以下方法查找课程:
stb_Swap_Tabu.ToString.Contains("CourseName")
就我而言,性能是最重要的问题。
有没有更快的方法?StringBuilder并不是真的用于所有字符串目的。如果您真的需要搜索一个,您必须编写自己的方法
有几种适合不同情况的字符串搜索算法
下面是Knuth–Morris–Pratt算法的一个简单实现,该算法只关心顺序匹配(没有大小写折叠,没有与区域性相关的排序,只是简单的码点到码点匹配)。它有一些初始的Θ(m)
开销,其中m
是所查找单词的长度,然后在Θ(n)
中查找,其中n
是到所查找单词的距离,或者如果不存在,则是整个字符串生成器的长度。这胜过了简单的逐字符比较,即Θ((n-m+1)m)
(其中O()
表示法描述上界,Θ()
同时描述上界和下界)
尽管如此,创建一个列表可能是完成手头任务的更好方法
public static class StringBuilderSearching
{
public static bool Contains(this StringBuilder haystack, string needle)
{
return haystack.IndexOf(needle) != -1;
}
public static int IndexOf(this StringBuilder haystack, string needle)
{
if(haystack == null || needle == null)
throw new ArgumentNullException();
if(needle.Length == 0)
return 0;//empty strings are everywhere!
if(needle.Length == 1)//can't beat just spinning through for it
{
char c = needle[0];
for(int idx = 0; idx != haystack.Length; ++idx)
if(haystack[idx] == c)
return idx;
return -1;
}
int m = 0;
int i = 0;
int[] T = KMPTable(needle);
while(m + i < haystack.Length)
{
if(needle[i] == haystack[m + i])
{
if(i == needle.Length - 1)
return m == needle.Length ? -1 : m;//match -1 = failure to find conventional in .NET
++i;
}
else
{
m = m + i - T[i];
i = T[i] > -1 ? T[i] : 0;
}
}
return -1;
}
private static int[] KMPTable(string sought)
{
int[] table = new int[sought.Length];
int pos = 2;
int cnd = 0;
table[0] = -1;
table[1] = 0;
while(pos < table.Length)
if(sought[pos - 1] == sought[cnd])
table[pos++] = ++cnd;
else if(cnd > 0)
cnd = table[cnd];
else
table[pos++] = 0;
return table;
}
}
公共静态类StringBuilderSearching
{
公共静态布尔包含(此StringBuilder草垛、字符串指针)
{
返回草垛。索引(针)!=-1;
}
公共静态int IndexOf(此StringBuilder haystack,字符串指针)
{
如果(草堆==null | |针==null)
抛出新ArgumentNullException();
如果(指针长度==0)
返回0;//到处都是空字符串!
if(needle.Length==1)//不能仅仅通过旋转来实现
{
字符c=针[0];
for(intidx=0;idx!=haystack.Length;++idx)
if(haystack[idx]==c)
返回idx;
返回-1;
}
int m=0;
int i=0;
int[]T=KMPTable(针);
而(m+i-1?T[i]:0;
}
}
返回-1;
}
私有静态int[]KMPTable(寻找字符串)
{
int[]表=新的int[sequed.Length];
int pos=2;
int cnd=0;
表[0]=-1;
表[1]=0;
while(位置<表格长度)
如果(被搜索[pos-1]==被搜索[cnd])
表[pos++]=++cnd;
否则,如果(cnd>0)
cnd=表[cnd];
其他的
表[pos++]=0;
返回表;
}
}
我知道这是一个老问题,但当我试图为自己的项目创建解决方案时,它出现在我的搜索结果中。我以为我需要搜索StringBuilder.ToString
的方法结果,但后来我意识到我可以在StringBuilder
本身上调用方法。我的情况可能与你的不一样,但我想我会分享:
Private函数valueFormatter(ByVal值作为字符串)作为字符串
'这将更正任何格式,使该值对CSV格式有效
'
“1)任何值,作为一个,在它里面,那么它必须被包装在一个“即,你好,世界->你好,世界”
“2)为了在值中转义一个”,请添加一个“即Hello”世界->Hello”世界
“3)如果该值中包含一个”,则它还必须包装为一个“即“Hello World”->“Hello World”->“Hello World”->“Hello World”
'
“不,太好了
' " -> """"
' "" -> """"""
如果value.Contains(“,”)或value.Contains(“”),则
将某人调整为新的StringBuilder(值)
如果value.Contains(“”),则sb.Replace(“”,“”)
sb.插入(0,“”)。追加(“”)
使某人恢复原状
其他的
返回值
如果结束
端函数
如果您需要使用StringBuilder
,那么您可能需要在每次搜索时调用ToString
,这在性能方面不是一个好主意。StringBuilder
用于构建字符串;假设您正在构建字符串,那么您已经拥有了组成部分;为什么不在t中搜索呢直接连接组成部分?StringBuilder
可能是最不适合存储可搜索名称列表的数据类型。为什么不使用列表
,并使用列表
的包含
方法?你有没有这个字符串的实际示例?你说它存储“课程名称”“-无论“课程”是否真正意味着“课程”,“名称”表示不止一个名称-因此,这可能是一个带分隔符的字符串。在这种情况下,将其切换到单个名称的列表
或哈希集
,对于较大数量的字符串,列表
对于较小的字符串,将非常有意义。我同意这不太可能是这里需要的。尽管如此,在StringBuilder中查找子字符串还是会出现。正如@JonHanna提到的,我有一个很好的理由拥有一个生成器,这就是为什么我的问题标题是:StringBuilder中最快的搜索方法。根据我的测试结果,@JonHanna经过一些修改后给出的答案比使用Conatins
要好28%。我将尝试制作抽象代码并在这里共享。StringBuilder有一个Replace
函数,它必须不可避免地搜索字符串,甚至需要开始和结束索引,但没有提供indexOf
函数,这是没有意义的。为什么我们要重做已经做过的事情呢?对于我来说,这个代码失败了,haystack“abcde”和needle“cd”,它返回false。它不应该是返回m代码>,不是返回m==针的长度-1:m代码>?@JuriRobl该位与未找到的.NET约定-1匹配。我不知道是什么导致了这次失败,如果有机会,我会稍后再看。