0

I have multiple arrays of strings and I'm trying to figure out an efficient way to loop through them for a match and if a match is found, leave the loop. For each array I'm already using a loop to check for matches. There ought to be a better way to do this than just to repeat the inner loop in code for each and every array but I can't figure out how to do it.

Here is my code. It only shows 3 arrays but I'd like to eventually expand this to many more arrays so the code will become more and more inefficient.

    $query = $_Request['q'];//query from Internet
    $arrayMovies = array("La Dolce Vita","East of Eden","North by Northwest");
    $arrayDirectors = array("Fellini","Ray","Hitchcock");
    $arrayActors = array("Giancarlo","James","Jimmy");
    $match = "";
    $type = "";
    $phrases = $arrayMovies;

    foreach($phrases as $phrase)
    {
      if(preg_match("/" . $phrase . "/i", $query))
      {
        $match = $phrase;
        $type = "movie";
      }
    }

    //repeat for next array
    $phrases = $arrayDirectors;
    foreach($phrases as $phrase)
    {
      if(preg_match("/" . $phrase . "/i", $query))
      {
        $match = $phrase;
        $type = "director";
      }
    }

    //repeat for next array
    $phrases = $arrayActors;
    foreach($phrases as $phrase)
    {
      if(preg_match("/" . $phrase . "/i", $query))
      {
        $match = $phrase;
        $type = "actor";
      }
    }

    if ($match!="") {
      //DO SOMETHING
    }

Is there a way to loop through the arrays and the first time we find a match leave the loop and do something with the match?

M M
  • 3
  • 2
  • Possible duplicate of [How to search in an array with preg\_match?](https://stackoverflow.com/questions/8627334/how-to-search-in-an-array-with-preg-match) – Jb31 Jul 17 '19 at 18:28
  • 1
    Aren't your variables in `preg_match` backwards? And simple string matching (`stristr`) should work, given your example. – msg Jul 17 '19 at 18:51
  • The linked to question is about how to get the match which is already working. My issue is with how to manage looping when working with multiple arrays. – M M Jul 17 '19 at 22:26

2 Answers2

0

You can use array_merge to combine your arrays into a single array. Then you only need to loop through it once. You can use the continue key word to escape the loop when you have found a match.

<?php

$query = 'James';//query from Internet
$arrayMovies = array("La Dolce Vita","East of Eden","North by Northwest");
$arrayDirectors = array("Fellini","Ray","Hitchcock");
$arrayActors = array("Giancarlo","James","Jimmy");
$match = null;
$phrases = array_merge($arrayMovies, $arrayDirectors, $arrayActors);

foreach($phrases as $phrase)
{
    if(preg_match("/" . $phrase . "/i", $query))
    {
        $match = $phrase;
        continue;
    }
}

if (!empty($match)) {
    echo 'Found a match for ' . $match;
}

Alternatively, you don't need to loop through the array. You can use preg_grep to search your array once it is merged. http://php.net/manual/en/function.preg-grep.php

Jason Houle
  • 310
  • 2
  • 7
  • This would work if I could preserve info that I've matched a director or a movie or an actor as I need this. Can you see a way to preserver which array it came from? – M M Jul 17 '19 at 22:18
  • preg_grep is a great suggestion for a quick filter. – Progrock Jul 18 '19 at 09:37
0

Two examples here. You could return early using a function, or breakout a loop. Note both methods will short-circuit after the first match.

<?php

$arrayDirectors = array("Fellini","Ray","Hitchcock");
$arrayMovies    = array("La Dolce Vita","East of Eden","North by Northwest");

function keyword_search($keyword, $array) {
    foreach($array as $value)
        if (preg_match("/\b" . preg_quote($keyword) . "/i", $value))
            return true;
}

if(keyword_search('Hitch', $arrayDirectors))
    echo 'Search term found in directors.';

Output:

Search term found in directors.

To find which collection you obtain a match:

<?php
foreach(['directors' => &$arrayDirectors, 'movies' => &$arrayMovies] as $collection => $v)
{
    if(keyword_search('eden', $v)) {
        $matched = $collection;
        break;
    }
}

echo $matched;

Output:

movies

I've added a word boundary to your regex, otherwise it's easy to match prematurely/or over match IMHO.

But you'll probably want to match multiple titles. In which case you might want to filter your arrays instead:

<?php
$arrayMovies = array("North to Alaska","East of Eden","North by Northwest","Westworld");

function keyword_filter($keyword, $array) {
    return array_filter($array, function($value) use ($keyword) {
        return preg_match("/\b" . preg_quote($keyword) . "/i", $value);
    });
}    

var_export(keyword_filter('north', $arrayMovies));
echo "\n";
var_export(keyword_filter('west', $arrayMovies));

Output:

array (
    0 => 'North to Alaska',
    2 => 'North by Northwest',
)
array (
    3 => 'Westworld',
)
Progrock
  • 7,373
  • 1
  • 19
  • 25