C# 这是搜索子字符串最有效的方法吗?
我正在使用一些代码,这些代码返回一个代码来指示用户的类型(例如“a”、“B”、“C”、“D”等)。每个代码对应一个特定的角色和/或范围(例如,在整个应用程序中或仅针对正在处理的对象) 在我正在查看的一些代码中,我看到了一些调用,这些调用用于检查用户的代码是否是多个代码中的一个,以便允许他们执行某些操作。所以我看到这样的电话:C# 这是搜索子字符串最有效的方法吗?,c#,performance,C#,Performance,我正在使用一些代码,这些代码返回一个代码来指示用户的类型(例如“a”、“B”、“C”、“D”等)。每个代码对应一个特定的角色和/或范围(例如,在整个应用程序中或仅针对正在处理的对象) 在我正在查看的一些代码中,我看到了一些调用,这些调用用于检查用户的代码是否是多个代码中的一个,以便允许他们执行某些操作。所以我看到这样的电话: //"B" would come from the database string userCode = "B"; //some more work... //if t
//"B" would come from the database
string userCode = "B";
//some more work...
//if the user's code is either A or C...
if("AC".IndexOf(userCode) >= 0) {
//do work that allows the user to progress
} else {
//notify user they can't do this operation
}
这是执行此检查的有效方法吗?有没有更有效的方法
提前谢谢 使用Contains()函数是一种选择。我不知道它相对于索引的性能如何,但它是一个选项:
string userCode = "B";
string someStringToSearchIn = "Current user is: B";
if (someStringToSearchIn.Contains(userCode))
{
//do something
}
如果要查找单个字符,并且它不区分大小写,请使用与字符一起工作的重载。搜索单个不区分大小写的字符比搜索子字符串快
"AC".IndexOf('C');
不过,这对于这件事来说是至关重要的。用任何明显的方法,你所做的都会非常快
更新-计时
[Test]
public void Time()
{
const string UserCode = "C";
const char UserCodeChar = 'C';
const int Iterations = 10000000;
double adjust = 0;
Func<Action, double> time = action =>
{
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++) action();
return sw.Elapsed.TotalMilliseconds;
};
Action<string, Action> test = (desc, t) =>
{
double ms = time(t) - adjust;
Console.WriteLine(desc + " time: {0}ms", ms);
};
adjust = time(() => { });
test("IndexOfString", () => "AC".IndexOf(UserCode));
test("IndexOfString", () => "AC".IndexOf(UserCode));
test("ContainsString", () => "AC".Contains(UserCode));
test("ContainsString", () => "AC".Contains(UserCode));
test("IndexOfChar", () => "AC".IndexOf(UserCodeChar));
test("IndexOfChar", () => "AC".IndexOf(UserCodeChar));
}
[测试]
公共空闲时间()
{
常量字符串UserCode=“C”;
const char UserCodeChar='C';
const int迭代次数=10000000;
双重调整=0;
Func time=操作=>
{
秒表sw=Stopwatch.StartNew();
对于(int i=0;i
{
双ms=时间(t)-调整;
Console.WriteLine(desc+“时间:{0}ms”,ms);
};
调整=时间(()=>{});
测试(“IndexOfString”,()=>AC.IndexOf(UserCode));
测试(“IndexOfString”,()=>AC.IndexOf(UserCode));
测试(“ContainsString”,()=>“AC”.Contains(UserCode));
测试(“ContainsString”,()=>“AC”.Contains(UserCode));
测试(“IndexOfChar”,()=>AC.IndexOf(UserCodeChar));
测试(“IndexOfChar”,()=>AC.IndexOf(UserCodeChar));
}
结果:
索引字符串时间:1035.2984ms索引字符串时间:1026.2889毫秒
包含字符串时间:764.9274ms
包含字符串时间:736.7621ms
IndexOfChar时间:92.9008ms
IndexOfChar时间:92.9961ms
查看
Contains()
的反编译代码,它只调用IndexOf()
和StringComparison.Ordinal
,因此我认为IndexOf()
如果以相同的方式(Ordinal)使用,效率最高(非常小),因为它只有一个方法调用,但是Contains()
更具可读性,因此更易于维护
public bool Contains(string value)
{
return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}
正如所有事情一样,我会选择可读性和可维护性更好的,然后再对性能进行微调。只有当您知道此时存在瓶颈时才进行微观优化
更新:超过1000000次迭代:
- 包含(值)-耗时130毫秒
- IndexOf(value,StringComparison.Ordinal)-耗时128毫秒
- 包含(字符值)-耗时94毫秒
- IndexOf(字符值)-耗时16毫秒
IndexOf()
大约快一个数量级
这是因为Contains(char-value)
是IEnumerable
的扩展方法,而不是string
的第一类方法
但是再一次,100万次迭代中的100毫秒实际上是可以忽略不计的。我认为您可以假设系统库的实现非常有效,并且您通常无法使用自制的解决方案来加快速度。也就是说,我认为您编码用户类型的方式非常奇怪。为什么不使用位掩码或类似的东西呢?除此之外,我认为你的问题根本不重要:与访问数据库和做“一些工作”相比,你的检查根本不重要。至少在我的电脑上,
包含字符串的(而不是字符的)是最快的
结果:
时间索引:616ms
包含时间:499ms
包含字符时间:707ms
代码:
static void Main(字符串[]args)
{
字符串userCode=“B”;
char userCodeChar='B';
整数迭代次数=10000000;
var sw=Stopwatch.StartNew();
对于(int i=0;i=0)
{
INTA=1+1;
}
}
sw.Stop();
WriteLine(“IndexOf time:{0}ms”,sw.elapsedmillesons);
sw=秒表。开始新();
对于(int i=0;i
首先,我不太清楚您为什么关心这里的效率。您正在执行非常短的字符串搜索,这不太可能影响性能
尽管如此,我还是觉得这种风格令人困惑。如果您想知道userCode
是否是“A”和“C”中的一个,只需这样说:
if (userCode.Equals("A") || userCode.Equals("C"))
{
// Do something useful
}
晶莹剔透,最有可能的性能以及
作为补充说明,如果您可以将这些代码放入enum
,事情可能会简单得多:
[Flags]
public enum UserCode
{
None = 0,
A = 1,
B = 2,
C = 4
}
现在你可以说:
if ((userCode & (UserCode.A | UserCode.C)) != UserCode.None)
{
// Do something even more useful
}
这是落后的
if ((userCode & (UserCode.A | UserCode.C)) != UserCode.None)
{
// Do something even more useful
}