Re: Find keys in multidimensional array
[email protected] (Rene Veerman)
| Newsgroups | php.general |
|---|---|
| Message-ID | <CACMzB5fxZh2RERqwkYtBx8JpnFnnmE1DXud4dAByL-zVWvRW5w@mail.gmail.com> |
i have built some functions which do this sort of thing.
i'll share them with you..
function walkArray (&$a, $keyCallback=null, $valueCallback=null,
$callKeyForValues=false, $callbackParams=null, $k='', $level=0, $path='') {
// usage : walkArray ($someRecursiveArray, 'walkArray_printKey',
'walkArray_printValue');
// can handle recursive arrays. a nested array is a recursive array.
// is faster, especially on large arrays, than RecuriveArrayIterator, see
speed testing comment at
http://php.net/manual/en/class.recursiveiteratoriterator.php
// provides detailed information to callbacks on where in the data we are,
something that array_walk_recursive just doesnt do.
// passes data around as pointers, not copies of data.
if (!is_array($a)) {
return badResult (E_USER_ERROR, array (
'msg' => 'walkArray() was called but $a parameter passed is not
an array.'
));
} else {
foreach ($a as $k=>&$v) {
$cd = array ( // callback data
'type' => 'key',
'path' => $path,
'level' => $level,
'k' => &$k,
'v' => &$v,
'params' => &$callbackParams
);
if (!is_null($keyCallback) && ($callKeyForValues ||
is_array($v))) call_user_func ($keyCallback, $cd);
if (is_array ($v)) {
walkArray ($a[$k], $keyCallback, $valueCallback,
$callKeyForValues, $callbackParams, $k, $level+1, $path.'/'.$k);
} else {
$cd['type'] = 'value';
if (!is_null($valueCallback)) call_user_func
($valueCallback, $cd);
}
}
}
$r = true;
return goodResult($r);
}
function walkArray_printKey ($cd) {
echo '<div
style="background:blue;color:yellow;border-radius:5px;padding:2px;margin-top:5px;">'.PHP_EOL;
$indent = 20 * $cd['level'];
echo '<div style="padding-left:'.$indent.'px">'.PHP_EOL;
echo 'key : '.$cd['k'].'<br/>'.PHP_EOL;
echo 'path : '.$cd['path'].'<br/>'.PHP_EOL;
echo '</div>'.PHP_EOL;
echo '</div>'.PHP_EOL;
}
function walkArray_printValue ($cd) {
echo '<pre
style="background:green;color:white;border-radius:5px;padding:2px;margin-top:2px;">'.PHP_EOL;
$indent = 20 * $cd['level'];
echo '<div style="padding-left:'.$indent.'px">'.PHP_EOL;
echo 'key : '.$cd['k'].'<br/>'.PHP_EOL;
echo 'path : '.$cd['path'].'<br/>'.PHP_EOL;
echo 'value : '.$cd['v'].'<br/>'.PHP_EOL;
echo '</div>'.PHP_EOL;
echo '</pre>'.PHP_EOL;
}
function &chaseToPath (&$wm, $path, $create=false) {
//var_dump ($create); die();
//echo '$wm=<pre>'; var_dump ($wm);echo '</pre>'; //die();
//$path = str_replace ('/', '/d/', $path);
//$path .= '/d';
$nodes = explode ('/', $path);
foreach ($nodes as $idx=>$node) {
if (is_numeric($node) && is_string($node)) {
if (strpos($node,'.')===false) {
$nodes[$idx] = (int)$node;
} else {
$nodes[$idx] = (float)$node;
}
}
}
$chase = &chase ($wm, $nodes, $create);
//echo '$wm=<pre>'; var_dump ($wm);echo '</pre>'; die();
/*
$dbg = array (
'$path' => $path,
'$nodes' => $nodes,
'$wm' => $wm,
'$chase' => $chase
);
echo '$dbg=<pre style="background:red;color:yellow;">'; var_dump
($dbg); echo '</pre>';
*/
//die();
$false = false;
if (good($chase)) {
$arr = &result($chase);
return $arr;
} else return $false;
}
function &chase (&$arr, $indexes, $create=false) {
if (false) {
echo 'sitewide/functions.php --- $arr=<pre>'; var_dump ($arr); echo
'</pre>';
echo 'sitewide/functions.php --- $indexes=<pre>'; var_dump
($indexes); echo '</pre>';
echo 'sitewide/functions.php --- $create=<pre>'; var_dump
($create); echo '</pre>';
}
$r = &$arr;
foreach ($indexes as $idx) {
//echo 'sitewide/functions.php --- $idx=<pre>'; var_dump
($idx); var_dump (array_key_exists($idx,$r)); var_dump ($r); echo '</pre>';
if (
is_array($r)
&& (
$create===true
|| array_key_exists($idx,$r)
)
) {
if ($create===true && !array_key_exists($idx,$r))
$r[$idx]=array();
//echo 'sitewide/functions.php --- $idx=<pre>';
var_dump ($idx); echo '</pre>';
$r = &$r[$idx];
} else {
/*
$err = array(
'msg' => 'Could not walk the full tree',
'vars' => array(
'$idx--error'=>$idx,
'$indexes'=>$indexes,
'$arr'=>$arr
)
);
badResult (E_USER_NOTICE, $err);
*/
$ret = false; // BUG #2 squashed
return $ret;
}
}
//echo 'sitewide/functions.php --- $r=<pre>'; var_dump ($r); echo
'</pre>';
return goodResult($r);
}
function &chaseToReference (&$array, $path) {
if (!empty($path)) {
if (empty($array[$path[0]])) {
$err = array(
'msg' => 'Could not walk the full tree',
'$path' => $path,
'$array (possibly partially walked)' => $array
);
return badResult (E_USER_NOTICE, $err);
} else return chaseToReference($array[$path[0]], array_slice($path, 1));
} else {
return goodResult($array);
}
}
function good($r) {
return (
is_array($r)
&& array_key_exists('result',$r)
);
}
function &result(&$r) {
return $r['result'];
}
function &resultArray (&$r) {
$r2 = array();
foreach ($r as $k => $v) {
$r2[$k] = result($v);
}
return $r2;
}
function &goodResult(&$r) {
$r2 = array (
'isMetaForFunc' => true,
'result' => &$r
);
return $r2;
}
On Thu, Feb 25, 2021 at 7:59 AM <[email protected]> wrote:
> Hello. I have a multidimensional array.
>
> Some 'routes' only go 2-3 key/values down, While other options have
> 6-10 keys deep (Ive not planned this as yet - just started)..
>
> In the below array (just random words) I'm 'at' the 'Ginger' option
> now. I am wondering if there was a quick way of searching the array
> for 'Ginger' and finding the path "up" the array to get the key 2
> levels up.
>
> So for this example i'll want to go 'up' 2 levels to get 'crackers'
>
> (each unique key, will have a TITLE value, and a number of OPTIONS -
> 2-6 options each)
>
> Is there a quick way of doing this ?
>
> EXAMPLE array:-
>
> (
> [top] => Array
> (
> [CRUSH] => Array
> (
> [TITLE] => Crush
> [OPTION1] => Array
> (
> [cheese] => Array
> (
> [TITLE] => Cheese option
> )
>
> )
>
> [OPTION2] => Array
> (
> [crackers] => Array
> (
> [TITLE] => crackers
> [OPTION1] => Array
> (
> [NAME] => crackers option 1
> [Ginger] => Array
> (
> [TITLE] => Ginger
> title1
> [TITLE2] => Ginger
> title2
> )
>
> )
>
> [OPTION2] => crackers option 2
> )
>
> )
>
> )
>
> )
>
> )
>
>
>
>
>
> --
>
> Gordon.
>