2017-03-16 4 views
0

Nach dieser Frage: Pattern for check single occurrency into preg_match_allWas ist effizienter zwischen str_pos und preg_match?

Ich verstehe, dass mein Muster nur ein Wort pro Zyklus enthalten muss, weil in dem Fall, in dieser Frage berichtete, I „Microsoft“ und „Microsoft Exchange“ finden muß, und ich kann nicht ändere meine Regexp, weil diese beiden Möglichkeiten dynamisch aus einer Datenbank stammen!

Also meine Frage ist: Welches ist die bessere Lösung zwischen über 200 preg_match und die gleiche Anzahl von str_pos zu überprüfen, ob eine Teilmenge von char diese Wörter enthält?

Ich versuche, den möglichen Code für beide Lösung zu schreiben:

$array= array(200+ values); 
foreach ($array as $word) 
{ 
    $pattern='<\b(?:'.$word.')\b>i'; 
    preg_match_all($pattern, $text, $matches); 
    $fields['skill'][] = $matches[0][0]; 
} 

die Alternative ist:

$array= array(200+ values); 
foreach ($array as $word) 
{ 
    if(str_pos($word, $text)>-1) 
    { 
    fields['skill'][] = $word; 
    } 
} 
+0

REGEX-basierte Funktionen sind langsamer als die meisten anderen String-Funktionen. Übrigens kann Ihr Test es auch mit einem Regex machen, wenn Sie es wie folgt machen: $ pattern = '<\ b (?:'. $ Word1. '|'. $ Word2. '|'. $ Word3. '|' . $ word4. ') \ b> i'; 'und wie viele Wörter Sie gleichzeitig verwenden können, hängt davon ab, wie lang die Regex sein kann. Ich habe bei Test Regex erstellt, die 12004 Zeichen lang war. Scheint nicht die max. – JustOnUnderMillions

+0

'str_pos()' ist in der Regel 3-20x schneller als preg_match, weil preg_match hauptsächlich verwendet wird, um das Format einer Zeichenkette zu untersuchen und Teile davon basierend auf regulären Ausdrücken abzurufen. –

Antwort

1

strpos als preg_match viel schneller ist, ist hier eine Benchmark:

$array = array(); 
for($i=0; $i<1000; $i++) $array[] = $i; 
$nbloop = 10000; 
$text = <<<EOD 
I understand that my pattern must contain only a word per cycle because, in the case reported in that question, I must find "microsoft" and "microsoft exchange" and I can't modify my regexp because these two possibilities are given dinamically from a database! 

So my question is: which is the better solution between over 200 preg_match and the same numbers of str_pos to check if a subset of char contains these words? 
EOD; 

$start = microtime(true); 
for ($i=0; $i<$nbloop; $i++) { 
    foreach ($array as $word) { 
     $pattern='<\b(?:'.$word.')\b>i'; 
     if (preg_match_all($pattern, $text, $matches)) { 
      $fields['skill'][] = $matches[0][0]; 
     } 
    } 
} 
echo "Elapse regex: ", microtime(true)-$start,"\n"; 


$start = microtime(true); 
for ($i=0; $i<$nbloop; $i++) { 
    foreach ($array as $word) { 
     if(strpos($word, $text)>-1) { 
      $fields['skill'][] = $word; 
     } 
    } 
} 
echo "Elapse strpos: ", microtime(true)-$start,"\n"; 

Ausgang:

Elapse regex: 7.9924139976501 
Elapse strpos: 0.62015008926392 

Es ist etwa 13-mal schneller.

+0

Vielen Dank für Ihre sehr gute Antwort! – Filippo1980

1

REGEX basierte Funktionen sind slowers als die meisten anderen String-Funktionen.

Durch die Art und Weise Ihren Test auch mit einer regex tun können, wenn Sie es wie $pattern='<\b(?:'.$word1.'|'.$word2.'|'.$word3.'|'.$word4.')‌​\b>i'; tun und wie viele Wörter Sie können auf einmal verwenden, hängt davon ab, wie lange die Regex sein kann. Ich habe bei Test Regex erstellt, die 12004 Zeichen lang war. Scheint nicht die max.

Die Regex Version (Einzelgespräch):

$array= array(200+ values); 

$pattern='<\b(?:'.implode('|',$array).')\b>i'; 
preg_match_all($pattern, $text, $matches); 
//$fields['skill'][] = $matches[0][0]; 

strpos Version (Multi Anrufe)

$array= array(200+ values); 
foreach ($array as $word){ 
if(strpos($word, $text)!==false)//not with >-1 wont work. 
{ 
    fields['skill'][] = $word; 
} 
} 

Wenn Sie einzelne Wörter suchen, werden strpos Hello in HelloWorld, passen so, wenn Sie nur wollen echte sepreated Worte, können Sie tun:

$arrayOfWords = explode(' ',$string); 
//and now you can check array aginst array 
$array= array(200+ values); 
foreach ($array as $word){ 
if(in_array($word,$arrayOfWords))//not with >-1 wont work. 
{ 
    fields['skill'][] = $word; 
} 
} 
//you can makes this also faster if you array_flip the arrayOfWords 
//and then check with 'isset' (more faster than 'in_array') 

Dass Sie auch Wortkombinationen ("Microsoft Exchange") zuordnen möchten, ist auf diese Weise nicht möglich, wenn Sie diese Kombinationen nicht in Ihrer Wortliste haben.

* hinzugefügt Kommentare

+0

Vielen Dank für Ihre Antwort, aber Ihre Regexp haben ein Problem ...Wie gesagt, wenn ich nach "Microsoft" und "Microsoft Exchange" in derselben Phrase suche, wird Ihre Lösung nur ein Ergebnis finden! – Filippo1980

+0

@ Filippo1980 OK, aber die überprüfte Antwort wird auch nicht "Microsoft Exchange" nur dann, wenn Sie für "Microsoft Exchange" nicht "Microsoft" allein suchen, war meine Antwort mehr auf _Was ist schneller _. Und _my regexp_ ist das gleiche wie _your regexp_ nur whit auf der Suche nach mehr als einem Wort auf einmal ;-) Und Ihre Frage war wirklich über preformance nicht über die Ergebnisse, die Sie wollen. -> _So meine Frage ist: ..._ – JustOnUnderMillions

Verwandte Themen