I have keyphrases abc, xyz, pqr, mno, etc. Text - " this text contains abc and mno", want to find whether text contains keyphrase string. I am looking for an efficient solution.

    $content = " this text contains keyphrases abc and mno ";
    $tags    = array(array('key_phrase'=>'abc'),array('key_phrase'=>'pqr'),array('key_phrase'=>'mno'));
    foreach( $tags as $tag ){
        if( preg_match( "/".$tag['key_phrase']."/", $content ) ){
            echo "key_phrase present ".$tag['key_phrase'];
  • 1
    \$\begingroup\$ What "keyphrase" means? Is it a simple sub-string, something delimited by spaces, punctuation characters or string boundaries, is it a regex pattern or a literal string? Does it start and end with word characters? Is your search case-sensitive? Without a clear definition of what you call "keyphrase", it isn't possible to help you. \$\endgroup\$ Apr 29 '16 at 11:51
  • \$\begingroup\$ keyphrase is simple sub-string. \$\endgroup\$ May 1 '16 at 7:02

You should use the strpos function

You call strpos($content, $tag['key_phrase']), and if the result === false, it's not found. Otherwise, it is found.

It's faster than preg_match, and the preg_match documentation even says so.


If you are going to use a regex, I think you should use it to its full potential. You can easily get rid of you foreach and do all the matching with a single regex. Have a look at the following code, which has the exact same output as yours:

$content = " this text contains keyphrases abc and mno ";
$regex = '/(abc|pqr|mno)/';
$matches = [];
preg_match_all($regex, $content, $matches);
echo implode('', array_map(function($match) {
    return "key_phrase present $match";
}, $matches[0]));

Note that I used preg_match_all since it performs a global match (it doesn't stop after the first hit). Should you want to learn more about regular expressions, or to try them out (they may be a bit hard to understand sometimes, though this one is pretty straight forward), I recommend regex101.com. I use it all the time when I ned to write a regex.

strpos may be faster as @Devsman mentions, but it requires a loop. So I'm pretty sure this solution will scale much better. And for the length of the $content and the number of key_prhases you are using the diffrence is probably negligible anyway.

  • \$\begingroup\$ For the record, array_map() iterates like a loop. All sensible solutions will have to use a looping/iterating mechanism at some point. \$\endgroup\$ Jun 26 '17 at 5:36
  • \$\begingroup\$ ...declaring an empty $matches array is not necessary. Using a capture group in your pattern costs 170 steps, removing the parentheses drops the step count down to 128. You are not even using the captured results. If you are going to implode with an empty string, you can omit that parameter. If I was going to glue the results together I would at least use a comma or <br> or some kind of visible delimiter. \$\endgroup\$ Jun 26 '17 at 5:46
  • \$\begingroup\$ @mickmackusa perhaps you should review the OP's code in stead of mine... \$\endgroup\$
    – Pevara
    Jun 26 '17 at 5:49
  • \$\begingroup\$ I thought you might want to improve the quality of your answer. Just trying to help. I can delete my comment if you like. I'm not attacking you. \$\endgroup\$ Jun 26 '17 at 6:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.