Matching a recursive / multidimensional array with another array
I have the following array (called $example_array below):
array(3) { ["id"]=> string(4) "123" ["name"]=> array(1) { ["first"]=> string(3) "pete" ["last"]=> string(3) "foo" } ["address"]=> array(1) { ["shipping"]=> array(1) { ["zip"]=> string(4) "1234" ["country"]=> string(4) "USA" } } } I need a function that I can run against such arrays and look for a match. Here are the searches that I would like to perform:
// These should return true: search( $example_array, array( 'id' => '123' ) ); search( $example_array, array( 'name' => array( 'first' => 'pete' ) ); search( $example_array, array( 'address' => array( 'shipping' => array( 'country' => 'USA' ) ) ); // These don't have to return true: search( $example_array, array( 'first' => 'pete' ) ); search( $example_array, array( 'country' => 'USA' ) ); Is there an internal PHP function that I can use, or do I have to write something myself?
function search($array, $b) { $ok = true; foreach ($b as $key => $value) { if (!isset($array[$key])) { $ok = false; break; } if (!is_array($value)) $ok = ($array[$key] == $value); else $ok = search($array[$key], $value); if ($ok === false) break; } return $ok; } Here is a test script .
We hope this feature helps:
public function matchArray(&$arrayToSearch, $valueToMatch = array()){ if(!is_array($valueToMatch)) $valueToMatch = array($valueToMatch); $exists = false; $indexToMatch = array_keys($valueToMatch); foreach($indexToMatch as $ind){ if(array_key_exists($ind, $arrayToSearch)){ $valToMatch = $valueToMatch[$ind]; $value = $arrayToSearch[$ind]; $valType = gettype($value); $valToMatch = $valueToMatch[$ind]; if($valType == gettype($valToMatch) || is_numeric($valToMatch)){ if($valType == 'array'){ $exists = $this->matchArray($value, $valToMatch); } else if(($valType == 'string' || is_numeric($valToMatch)) && $valToMatch == $value) { $exists = true; } else { $exists = false; break; } } } } return $exists; } There is no built-in to do what you want, iirc.
Here's the (untested) version with array_walk :
function search($data,$match) { return array_walk($match, function($v,$k) use ($data) { if (isset($data[$k])){ if (is_array($v)) return search($data[$k],$v); return ($v == $data[$k]); }); return false; } This is somewhat concise (could it be better with ?: , But perhaps not very readable. Lambdas is a great addition to php!
Here's another possible solution, but apparently small (you have to check to make sure):
function search($d,$m) { return is_empty(array_diff_assoc(array_intersect_assoc($d,$m), $m)); } Maybe this will not work if inline use is not recursive.