5
$keywords = array('red', 'blue', 'yellow', 'green', 'orange', 'white');

$strings = array(
'She had a pink dress',
'I have a white chocolate',
'I have a green balloon',
'I have a chocolate shirt',
'He had a new yellow book',
'We have many blue boxes',
'I have a magenta tie');

In reality the strings array is really huge (50k+ entries).

What is the best way of running search and extracting the matching strings only?

Bengali
  • 198
  • 2
  • 13

2 Answers2

4

The best way is to use array_filter().

$filtered_array = array_filter($strings,'filter');

function filter($a)
{
    $keywords = array('red', 'blue', 'yellow', 'green', 'orange', 'white');

    foreach ($keywords as $k)
    {
        if (stripos($a,$k) !== FALSE)
        {
            return TRUE;
        }
    }

    return FALSE;
}
worldofjr
  • 3,868
  • 8
  • 37
  • 49
  • Didn't know you could actually pass an array to `stripos` – adeneo Dec 27 '15 at 16:55
  • If this or any answer has solved your question please consider [accepting it](http://meta.stackexchange.com/q/5234/179419) by clicking the check-mark. This indicates to the wider community that you've found a solution and gives some reputation to both the answerer and yourself. There is no obligation to do this. – worldofjr Dec 27 '15 at 16:56
  • 1
    And you can't, it throws `stripos(): needle is not a string or an integer` – adeneo Dec 27 '15 at 16:57
  • 1
    @adeneo Avoided this problem with a loop. Not the most elegant solution, but it works. – worldofjr Dec 27 '15 at 17:08
  • @Bengali You're probably not using >PHP5.5. Easily fixed, move the function out to be defined elsewhere, and reference it in `array_filter()`. – worldofjr Dec 27 '15 at 17:10
  • 1
    For performance reasons I would define `$keywords` outside of your filter function and include it with the use statement. – flec Dec 27 '15 at 17:12
4

Use array_filter to filter the $strings array.
Split the strings into an array, then trim each word, and use array_intersect to check if the array of words contains any of the $keywords.

$result = array_filter($strings, function($val) use ($keywords) {
    return array_intersect( array_map('trim', explode(' ', $val)) , $keywords);
});
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • 1
    I would rather use the use statement in you lambda function instead of the global keyword. – flec Dec 27 '15 at 17:06
  • @flec - I really don't like `use`, but as the keywords probably doesn't change, there shouldn't be any issues here, so I agree, and edited. – adeneo Dec 27 '15 at 17:13