2009-12-05 32 views
1

我需要在文本中找到以[開頭並且以]結尾的所有內容,並將其替換爲函數返回的值。所以,這裏是我正在做的一個例子:替換C#中的正則表達式匹配集合

public string ProcessTemplate(string input) 
    { 
     return Regex.Replace(input, @"\[(.*?)\]", new MatchEvaluator(delegate(Match match) 
      { 
       return ProcessBlock(match.Result("$1")); 
      })); 
    } 

    public string ProcessBlock(string value) 
    { 
     return Block.FromString(value).Process(); 
    } 

現在,我的問題是當我需要編輯塊。所以我想找塊,編輯它們,然後然後在文本中替換它們。

所以,我創建塊的列表,並分離ProcessTemplate法兩種方法:FindBlocksReplaceBlocks

public void FindBlocks(string input) 
    { 
     Input = input; 

     foreach (Match match in Regex.Matches(input, @"\[(.*?)\]")) 
      Blocks.Add(Block.FromString(match.Result("$1"))); 
    } 

    public string ReplaceBlocks() 
    { 
     string input = Input; 

     foreach (Block block in Blocks) 
      input = input.Replace("[" + block.OrginalText + "]", block.Process); 

     return input; 
    } 

    public IList<Block> Blocks 
    { 
     get; 
     set; 
    } 

    public string Input 
    { 
     get; 
     set; 
    } 

它的工作,但問題是,它是相當緩慢。我用System.Diagnostics.Stopwatch每個部分進行了測量,我發現ReplaceBlocks方法中的String.Replace非常慢。

我該如何改進?

謝謝。

+0

我不明白是什麼導致你放棄你的第一種方法,似乎是正確的解決方案。你能詳細說明嗎? – 2009-12-05 22:30:50

+0

馬克的權利:這正是MatchEvaluator的用途。另外,如果你想要第一個捕獲組的內容,'match.Groups [1]'比'match.Result(「$ 1」)'更有效率。 – 2009-12-06 08:48:52

回答

1

與一個StringBuilder替換ReplaceBlock字符串可以提供的性能提升,因爲每個在執行其與string.replace將要解除分配字符串並重新分配字符串的時間。字符串生成器不需要這樣做。

用以下內容替換ReplaceBlock的內容。

// This will require a reference to System.Text 
StringBuilder input =new StringBuilder(Input); 
    foreach (Block block in Blocks) 
    { 
    input = input.Replace("[" + block.OrginalText + "]", block.Process); 
    } 
    return input.ToString(); 

我還發現用更快的for循環替換foreach循環。

0

,我認爲它是緩慢

不要優化,直到你已經成型。找出代碼速度緩慢的原因,然後優化這些部分。

http://c2.com/cgi/wiki?ProfileBeforeOptimizing

+0

請參閱我的編輯。 – 2009-12-05 22:25:28

+0

太棒了!有一件事可能會更快,那就是當你最初匹配它時,存儲每個塊的字符偏移量。然後通過Substring替換該字符範圍,而不是使用string.Replace - 應該更快。當然,如果您替換的內容與原始內容的長度不一致,則每次更換後必須更新您的差異。更多的簿記,但最終可能會更快。 – kevingessner 2009-12-05 22:29:14

+0

@kevingessner:我試過:「input = input.Substring(0,block.Position)+ block.Process()+ input.Substring(block.Position + block.Length);」但它不工作... block.Position = match.Index和block.Length = match.Length。你知道它爲什麼不起作用嗎? – 2009-12-05 22:49:46