C#循环通过字符数组无效
我在下面有一段代码,我循环遍历字符串并逐字符比较所有内容,这是一个非常缓慢的过程,我想知道如何改进这段代码C#循环通过字符数组无效,c#,C#,我在下面有一段代码,我循环遍历字符串并逐字符比较所有内容,这是一个非常缓慢的过程,我想知道如何改进这段代码 //delete anti-xss junk ")]}'\n" (5 chars); if (trim) { googlejson = googlejson.Substring(5); } //pass through result and turn empty elements in
//delete anti-xss junk ")]}'\n" (5 chars);
if (trim)
{
googlejson = googlejson.Substring(5);
}
//pass through result and turn empty elements into nulls
//echo strlen( $googlejson ) . '<br>';
bool instring = false;
bool inescape = false;
string lastchar = "";
string output = "";
for ( int x=0; x< googlejson.Length; x++ ) {
string ch = googlejson.Substring(x, 1);
//toss unnecessary whitespace
if ( !instring && ( Regex.IsMatch(ch, @"/\s/"))) {
continue;
}
//handle strings
if ( instring ) {
if (inescape) {
output += ch;
inescape = false;
} else if ( ch == "\\" ) {
output += ch;
inescape = true;
} else if ( ch == "\"") {
output += ch;
instring = false;
} else {
output += ch;
}
lastchar = ch;
continue;
}
switch ( ch ) {
case "\"":
output += ch;
instring = true;
break;
case ",":
if ( lastchar == "," || lastchar == "[" || lastchar == "{" ) {
output += "null";
}
output += ch;
break;
case "]":
case "}":
if ( lastchar == "," ) {
output += "null";
}
output += ch;
break;
default:
output += ch;
break;
}
lastchar = ch;
}
return output;
到那
string ch = googlejson[x].ToString();
第二,我用字符串生成器替换了all+=ch
output.Append(ch);
因此,这两个更改对性能的影响最大。首先,当只处理单个字符时,不应使用
子字符串。使用
char ch = googlejson[x];
相反
您也可以考虑使用<代码> StringBuilder <代码>为您的代码>输出< /代码>变量。如果您使用字符串,您应该始终记住,字符串在.NET中是不可变的,所以对于每个
output += ch;
创建了一个新的字符串实例
使用
及
相反。根据其他注释,这段代码使用字符串作为字符和子字符串()在性能方面非常糟糕。
此外,使用正则表达式检查空白将是非常低效的
如果要对字符进行操作,请使用字符(char)而不是字符串
for循环有点低效,但JIT编译器可能会对此进行优化。使用局部变量而不是访问Length属性会稍微好一些
当打开字符的速度非常快时,打开字符串也是非常低效的
正如MartinStettner所建议的,StringBuilder append将更好地构建结果。(@Tom Squires-这个问题都是关于性能的,所以是的,它确实很重要,而且它并不复杂-可能会多几个角色,但这并不复杂
最后,我会说,如果你有性能问题(除了这个可怕的代码),你应该考虑在进行优化之前先用一个分析器测量它。
PS这看起来像一个面试问题……啧啧啧啧如果是这样,那就不是问题所在。
为什么不使用代替子字符串
var output = new StringBuilder();
using (var reader = new StringReader(googleJson)
{
var buffer = new char[1]
while (reader.Read(buffer, 0, 1) == 1)
{
var ch = buffer[0];
//your stuff
output.Append(ch);
}
}
return output.ToString();
您可以使用StringReader.Read()
并对字符的整数代码值执行所有逻辑操作,这可能会很快,但有点脆弱。关于:
if(!instring&&(Regex.IsMatch(ch,@/\s/)))
到
if(!instring&ch<33)
或者更好:
if(!instring&&Char.IsWhiteSpace(ch))
在任何现代系统上,StringBuilder的性能增益都是如此之小,以至于复杂性的增加毫无意义@Tom Squires,它真的有那么复杂吗?@Jodrell它不太复杂,但性能增益可以忽略不计,即使是少量的额外复杂性也不值得。@TomSquires that link解决了这样的问题不在循环中。当它不是循环时,c#将+
替换为String.Concat
。在循环中StringBuilder
使用是必要的,不要相信你读到的所有内容-profile!这不完全正确。对于小示例(如你提到的帖子中的示例)当然,差别很小。对于只有10个附录,二次复杂度并不重要(同样,如果在新字符串上运行相同的10个附录数千次…)但在这里介绍的循环中,它确实很重要。我做了一个简单的测试,添加一个字符10000次。StringBuilder的时间为7ms,+=
串联的时间为3238ms!!所以我认为,如果你在循环中添加字符,你应该始终使用StringBuilder(如果你需要多次迭代)不要这样做<代码> GoGoLyjs.Sub(x,1)因为代码只有一个<代码> for循环< /代码>,我认为它很慢,不是因为代码不高效,而是因为代码复杂。没有考虑改进您的方法(因为我不知道您的要求),如果您担心UI的无响应时间过长,我建议您将该函数放在backgroundworker中,如果您还没有实现progressbar,则可以实现它。我认为您会发现StringReader.Read()调用的开销超过了简单的googleJson[I]。StringReader()的分配/初始化也没有必要,对于小循环可能是可测量的。
StringBuilder output = new StringBuilder();
output.append(ch);
var output = new StringBuilder();
using (var reader = new StringReader(googleJson)
{
var buffer = new char[1]
while (reader.Read(buffer, 0, 1) == 1)
{
var ch = buffer[0];
//your stuff
output.Append(ch);
}
}
return output.ToString();