2011-03-01 40 views
0

我的iPhone應用程序使用正則表達式(與NSRegularExpression)來執行計算大量的字符串(在1000年)。這當然需要很多時間。什麼是加速正則表達式的一些策略?我研究過使用塊,但我認爲它不會有什麼好處 - 它們似乎主要表示lambda功能(即相當於lisp),並在具有多個內核的Mac上使用。顯然,目前的iPhone沒有多核心。如何加快與NSRegularExpression iPhone正則表達式?

這裏是我的代碼:

NSString *replaceRegexPattern = @"([\\(|\\[].*?[\\)|\\]])|(^to)"; 
NSRegularExpression *replaceRegex = [[NSRegularExpression regularExpressionWithPattern:replaceRegexPattern 
                       options:NSRegularExpressionCaseInsensitive 
                       error:nil] retain]; 
NSArray *myArray = <some data>; 
NSString *myString, *compareValue; 
for (i = 0; i < [myArray count]; i++) { 
    myString = [myArray objectAtIndex:i]; 
    compareValue = [replaceRegex stringByReplacingMatchesInString:myString 
                  options:0 
                  range:NSMakeRange(0, [myString length]) 
                withTemplate:@""]; 
    // do things with compareValue 

} 

要回答以下問題,我在此代碼的目標是消除它要麼是用括號括起來在我的字符串任何文本,或用「到」開始。下面是一些例子:

  • 你好(掛機) - >你好
  • 你好(掛機[N]) - >你好
  • 爲了說 - >說
  • 爲了說(PF) - >說
+0

你表達刪除「爲」,「TO」,「來」和「如果你只關心一個案例,你可以通過刪除選項'NSRegularExpressionCaseInsensitive'來加速它。 – 2015-10-13 06:02:54

回答

0

因爲我不知道你到底想做什麼,所以很難給出有根據的建議,但看起來你的正則表達式可能會有所改進。

你真的想要匹配像(foo)[bar]|baz|這樣的字符串嗎?您不需要在字符類內部使用|交流發電機,因此除非您想與此處的第三個示例相匹配,否則請刪除|

然後,因爲你希望像琴絃(foo [bar] baz),你需要兩種括號的分開,你也可以加快你的正則表達式位:

@"^to |\\([^)]*\\)|\\[[^\\]]*\\]" 

此檢查to在開始然後去尋找一個開放的paren /托架,除了關閉parens /托架,還有一個閉合的托架/托架。這需要更少的回溯,所以它可能快一點。

您將無法使用單個正則表達式處理同類嵌套圓括號/括號((foo (bar) baz)),因爲它不再是正規的 - 除非您多次運行正則表達式替換操作,每一次嵌套級別都會執行一次。因此,如果運行正則表達式替換兩次,上面的示例將被刪除。

+0

感謝你的建議,我希望能夠匹配嵌套的括號,但它不是最重要的方面 – Jason 2011-03-01 10:54:14

+0

它也可以是這樣的嗎?(foo(bar)baz)'?因爲這個(任意嵌套)不再是普通語言,並且不能用正常的正則表達式來匹配。 – 2011-03-01 11:06:31

+0

對,我創建的正則表達式與[:(\ [^ \]] *(\ [[^ \]] * \])?[^ \)] * \)| \ [[^ \]] * \]'匹配, foo)','[bar]'和'(foo [b ar] baz)' – Jason 2011-03-01 12:08:00

0

加快該正則表達式是使用所有格量詞的最佳方式:

NSString *replaceRegexPattern = 
    @"^to\\s++|\\[[^\\[\\]]*+\\]|\\([^()]*+\\)"; 

在沒有匹配是可能的,因爲一個開口托架不是由正確的右括號匹配的情況下,防止*+我們知道的回溯會毫無意義。但成功匹配嘗試也更有效率,因爲正則表達式引擎不必保存使回溯成爲可能的狀態信息。

正如Tim指出的那樣,這將不匹配相同類型括號的嵌套實例,如((foo))[[bar]]。它匹配匹配括號內的任意數量的方括號,反之亦然。它不需要將這些內部支架正確配對,因此它將匹配例如(foo[)[(bar))]。您的原始正則表達式也是如此。

包含在字符類的開口括號防止像[[foo]((bar)片面匹配。

1

你確定正則表達式是正確的工具嗎?

如果你所要做的只是刪除圓括號中的文本,通過字符串的簡單char-by-char循環可以很容易地完成,甚至可以正確處理嵌套parens。

在僞代碼:

nesting_level = 0; 
while more_chars { 
     c = next_char; 
     if c == '(' or c == '[') 
      ++nesting_level; 
     else if c == ')' or c == ']' 
      --nesting_level; // check for nesting_level < 0 here? 
     else if nesting_level == 0 
      result += c; 
} 

顯然,做你自己的基準,但很有可能你會避免正則表達式的獲得更好的性能。

(如果你在乎檢測類似病態的東西「(你好]」,你可以簡單的遞歸下降到這個)