2010-02-26 88 views
4

任何人都可以帮助我如何优化这种方法吗?字符串替换方法的优化

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
{ 
    VirtualPathData path = base.GetVirtualPath(requestContext, values); 

    if (path != null) 
    { 
     string virtualPath = path.VirtualPath; 
     string condition = string.Empty; 

     if (virtualPath.Contains("?")) 
     { 
      condition = virtualPath.Substring(virtualPath.IndexOf("?")); 
      virtualPath = virtualPath.Substring(0, virtualPath.IndexOf("?")); 
     } 

     virtualPath = virtualPath.Replace(@"%C5%BD", "ž"); 
     virtualPath = virtualPath.Replace(@"%C4%90", "đ"); 
     virtualPath = virtualPath.Replace(@"%C4%86", "ć"); 
     virtualPath = virtualPath.Replace(@"%C4%8C", "č"); 
     virtualPath = virtualPath.Replace(@"%C5%A0", "š"); 

     virtualPath = virtualPath.ToLower().Replace(",", "-").Replace("%20", "-").Replace("&", "-"); 
     virtualPath = virtualPath.Replace(@"-amp;", "&"); 

     while (virtualPath.Contains("--")) 
     { 
      virtualPath = virtualPath.Replace("--", "-"); 
     } 

     path.VirtualPath = virtualPath + condition; 
    } 

    return path; 
} 

回答

4

在此代码中要扫描的字符串三次字符:

if (virtualPath.Contains("?")) 
{ 
    condition = virtualPath.Substring(virtualPath.IndexOf("?")); 
    virtualPath = virtualPath.Substring(0, virtualPath.IndexOf("?")); 
} 

相反,一次扫描,并使用结果的三倍。同时扫描一个字符,而不是一个字符串:

int pos = virtualPath.IndexOf('?'); 
if (pos != -1) { 
    condition = virtualPath.Substring(pos); 
    virtualPath = virtualPath.Substring(0, pos); 
} 

在这里,你正在做的几个替换相同的替换:

virtualPath = virtualPath.ToLower().Replace(",", "-").Replace("%20", "-").Replace("&", "-"); 

相反,你可以使用正则表达式匹配所有的人:

virtualPath = Regex.Replace(virtualPath.ToLower(), "(,|%20|&)", "-"); 

(这是否实际提供更好的性能必须用您的一些实际数据进行测试。尽管它已经是少操作,有设立正规expresson一些开销)


您正在使用一个循环来减少字符集群:

while (virtualPath.Contains("--")) 
{ 
    virtualPath = virtualPath.Replace("--", "-"); 
} 

相反,你可以使用正则表达式做一个单一的替换:

virtualPath = Regex.Replace(virtualPath, "-{2,}", "-"); 
+0

您也可以将' - {2,}'表达式合并到另一个:'(,|%20 |&| - {2,})' – 2010-02-26 14:03:10

+0

@Joel,我不能合并它,因为if我的输入是'foo&foo',输出将是'foo --- foo'。 – 2010-02-26 14:13:16

0

你最明显的第一步是使用StringBuilder而不是String。

字符串是不可变的类型。这意味着一旦创建,它的价值永远不会改变。因此,对于您在方法中进行的每次替换调用,程序将创建一个全新的String实例来存储结果,这是存储器和处理器密集型的。 (我这样说比较 - 你不会让你的机器最大限度地调用这个方法一次,但如果你称它为数千次,你一定会注意到!)

另一方面,StringBuilder一个设计用于在内存中操作字符串的类,每次更改字符串时都不必复制/重新创建内存。

因此,在正确的方向上的一个大的步骤应该是在你的方法开始使用此:

  StringBuilder sb = new StringBuilder(path.VirtualPath.ToLower()); 
      string condition = string.Empty; 

      int index = path.VirtualPath.IndexOf("?"); 

      if (index > -1) 
      { 
       condition = virtualPath.Substring(pos); 
       sb.Remove(0, index); 
      } 

      sb.Replace(@"%C5%BD", "ž") 
       .Replace(@"%C4%90", "đ") 
       .Replace(@"%C4%86", "ć") 
       .Replace(@"%C4%8C", "č") 
       .Replace(@"%C5%A0", "š") 
       .Replace(",", "-") 
       .Replace("%20", "-") 
       .Replace("&", "-") 
       .Replace(@"-amp;", "&"); 
      sb.Append(condition); 

请注意,我也做了.ToLower(早期),因为StringBuilder的不具有相当于,并且还注意到sb.Append,这又会阻止很多重写。

这是不是最佳的,因为它可以得到的,但它应该是相当的改善...

有一件事我错过了被取代的“ - ”。 StringBuilder没有“Contains”函数,但是您可以使用正则表达式在一次传递中捕获所有内容(而不是需要循环)。

希望能让你开始!