Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive search in PHP array with path

I have this haystack array:

$array = [
   [
      "name" => "Intro",
      "id" => "123",
      "children" => [
         "name" => "foo",
         "id" => "234",
         "children" => [
            "name" => "mur",
            "id" => "445",
         ]
      ]
   ],[
      "name" => "chapter one",
      "id" => "9876",
      "children" => [
         "name" => "foo",
         "id" => "712",
         "children" => [
            "name" => "bar",
            "id" => "888",
         ]
      ]
   ]
];

And this needle array: $needle = ["chapter one","foo","bar"]

I'm working on a recursive search function that will return the id value of the child element matching on column name following the path of $needle.

In the example, it should return 888. I have this so far but I don't find how to follow the $needle path as opposed to finding values assuming they're unique. Appreciate any help putting me on the right track.

function searchTree( $needle, $haystack, $strict=false, $path=array() )
{
   if( !is_array($haystack) ) {
      return false;
   }

   foreach( $haystack as $key => $val ) {
   if( is_array($val) && $subPath = searchTree($needle, $val, $strict, $path) ) {
      $path = array_merge($path, array($key), $subPath);
      return $path;
   } elseif( (!$strict && $val == $needle) || ($strict && $val === $needle) ) {
      $path[] = $key;
      return $path;
   }
    }
    return false;
}
like image 928
greener Avatar asked Sep 28 '22 04:09

greener


1 Answers

I'll try to clean it up a bit, but this works:

$needle = ["chapter one", 'foo', 'bar'];
$array = [
    [
        "name" => "Intro",
        "id" => "123",
        "children" => [
            "name" => "foo",
            "id" => "234",
            "children" => [
                "name" => "mur",
                "id" => "445",
            ]
        ]
    ],[
        "name" => "chapter one",
        "id" => "9876",
        "children" => [
            "name" => "foo",
            "id" => "712",
            "children" => [
                "name" => "bar",
                "id" => "888",
            ]
        ]
    ]
];

function searchTree($needle, $haystack, $strict=false) {
    if(!is_array($haystack)) {
        return false;
    }
    $match = false;
    if(array_keys($haystack) !== range(0, count($haystack) - 1) && !empty($needle)) {
        if(($strict && $haystack['name'] === $needle[0]) || (!$strict && $haystack['name'] == $needle[0])) {
            $match = true;
            array_shift($needle);
            if (!empty($needle)) {
                return searchTree($needle, $haystack['children'], $strict);
            }
        }
    } else {
        foreach ($haystack as $key => $value) {
            if (is_array($value) && !empty($needle)) {
                if (($strict && $value['name'] === $needle[0]) || (!$strict && $value['name'] == $needle[0])) {
                    $match = true;
                    array_shift($needle);
                    if (!empty($needle)) {
                        return searchTree($needle, $value['children'], $strict);
                    } else {
                        $haystack = $haystack[$key];
                    }
                }
            }
        }
    }
    return (isset($haystack['id']) && $match) ? $haystack['id'] : false;
}

echo searchTree($needle, $array);

output:

888
like image 144
backend_dev_123 Avatar answered Oct 03 '22 03:10

backend_dev_123