1

I'm trying to search a multidimensional array for a partial string. My array looks like this:

$data = array(
    "United Kingdom" => array(
        "AFXX0001" => "Nottingham",
        "AFXX0002" => "Notting Hill",
    ),
    "Germany" => array(
        "ALXX0001" => "Garnottheinem",
        "ALXX0002" => "Tirane",
    ),
);

I'm trying to build a search function that will display all results which meet the partial match requirement. So far my function looks like this:

function array_find( $needle, $haystack )
{
    foreach ($haystack as $key => $array) {
        foreach ( $array as $key2 => $value ) {
            if (false !== stripos($needle, $value)) {
                $result = $key . ' ' . $value . ' ' . $key2;
                return $result;
            }
        }
    }
    return false;
}

It works, but only if I enter the actual value, eg array_find( 'Nottingham', $data );.

If I do array_find( 'nott', $data ); I would want it to return Nottingham, Notting Hill and Garnottheinem, but instead it returns bool(false).

Ian
  • 865
  • 5
  • 18
  • 29
  • 1
    even if it did find a match, you would only return the first result because you are returning when a match is found. I would suggest looking at array_filter for getting multiple results with your own comparison function. stripos should work fine for the partial match or you could use some sort of fuzzy "sounds like" function like [levenshtein](http://www.php.net/levenshtein) – Jonathan Kuhn Jul 16 '14 at 16:29

3 Answers3

2

In your stripos() call, you had the needle and haystack reversed.

Then concatenate the result list.

Try this:

function array_find( $needle, $haystack )
{

    $result = '';  //set default value

    foreach ($haystack as $key => $array) {
        foreach ( $array as $key2 => $value ) {
            if (false !== stripos($value,$needle))   // hasstack comes before needle
                {
                $result .= $key . ' ' . $value . ' ' . $key2 . '<br>';  // concat results
                //return $result;
            }
        }
    }

    return $result;
}
Jim
  • 576
  • 2
  • 11
2

Error in line:

if (false !== stripos($needle, $value)) {

Solution:

if (false !== stripos($value, $needle)) {
hmatt1
  • 4,939
  • 3
  • 30
  • 51
Cava
  • 5,346
  • 4
  • 25
  • 41
1
$data = array(
    "United Kingdom" => array(
        "AFXX0001" => "Nottingham",
        "AFXX0002" => "Notting Hill",
    ),
    "Germany" => array(
        "ALXX0001" => "Garnottheinem",
        "ALXX0002" => "Tirane",
    ),
);
$search = 'not';

$result = array();
array_walk_recursive(
    $data,
    function($item, $key) use ($search, &$result){
        $result[$key] = (stripos($item, $search) !== false) ? $item : null;
    }
);
$result = array_filter(
    $result
);
var_dump($result);

The equivalent using SPL Iterators rather than array_walk_recursive()

$result = array();
foreach (new RecursiveIteratorIterator(
             new RecursiveArrayIterator($data),
             RecursiveIteratorIterator::LEAVES_ONLY
         ) as $key => $value) {
         echo $key,PHP_EOL;
    $result[$key] = (stripos($item, $search) !== false) ? $item : null;
}
Mark Baker
  • 209,507
  • 32
  • 346
  • 385
  • Wouldn't it be better to just do `if(stripos($item, $search) !== false){$result[$key] = $item}`? That way you don't have to iterate over each value again with `array_filter($result)`. – imtheman Jul 16 '14 at 16:48
  • @imtheman - quite possibly, I was trying to come up with a clever solution that would include all levels of the key as well, but couldn't manage that easily, so went with what I had – Mark Baker Jul 16 '14 at 17:26
  • I like the `array_walk_recursive()`. I think that was quite clever. I never new about that function before. – imtheman Jul 16 '14 at 17:29
  • @imtheman - Sadly it ignores elements that are themselves arrays (which was how I was hoping to build the nested keys); I know that it's doable with SPL recursive iterators (where you can choose leaves only as an option) but that's a much more complex solution – Mark Baker Jul 16 '14 at 17:33
  • Oh, I see. Interesting. – imtheman Jul 16 '14 at 17:36