Recursion is the answer for this type of problem. Though, if we can make certain assumptions about the structure of the array (i.e., 'id' always be a leaf node with no children) there's further optimizations possible:
<?php $a = array( 'apple'=> array( 'new'=> array(array('id' => 1), array('id' => 2), array('id' => 5)), 'old'=> array(array('id' => 3), array('id' => 4, 'keyname' => 'keyvalue')) ), ); // When true the complete path has been found. $complete = false; function get_path($a, $key, $value, &$path = null) { global $complete; // Initialize path array for first call if (is_null($path)) $path = array(); foreach ($a as $k => $v) { // Build current path being tested array_push($path, $k); // Check for key / value match if ($k == $key && $v == $value) { // Complete path found! $complete= true; // Remove last path array_pop($path); break; } else if (is_array($v)) { // **RECURSION** Step down into the next array get_path($v, $key, $value, $path); } // When the complete path is found no need to continue loop iteration if ($complete) break; // Teardown current test path array_pop($path); } return $path; } var_dump( get_path($a, 'id', 3) ); $complete = false; var_dump( get_path($a, 'id', 2) ); $complete = false; var_dump( get_path($a, 'id', 5) ); $complete = false; var_dump( get_path($a, 'keyname', 'keyvalue') );