Re: Find keys in multidimensional array

From: Date: Thu, 25 Feb 2021 13:12:17 +0000
Subject: Re: Find keys in multidimensional array
References: 1 2 3  Groups: php.general 
Request: Send a blank email to php-general+get-327503@lists.php.net to get a copy of this message
Hello, I would like to suggest another solution... /** * Convert an array into a DOMDocument and use the power of DOMXPath */ function testRecreational () { $array = 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' ) ) ) ) ); $dom = new \DomDocument(); $walker = function($value, $key, $node) use(&$walker, &$dom){ if (is_string($value)) { $elt = $dom->createElement($key, $value); $node->appendChild($elt); } else if(is_array($value)) { $elt = $dom->createElement($key); $node->appendChild($elt); array_walk($value, $walker, $elt); } }; array_walk($array, $walker, $dom); $xpath = new \DOMXPath($dom); $nodes = $xpath->query("//crackers");// Or "//TITLE[contains(text(), 'crackers')]/.." for($node=$nodes[0]; $node; $node=$node->parentNode) { echo $node->nodeName, PHP_EOL;// It's your turn ;-) } } Have fun Kind regards, Serge Le jeu. 25 févr. 2021 à 10:54, Rene Veerman < rene.veerman.netherlands@gmail.com> a écrit : > 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 <gordonisnz@gmail.com> 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. >> >

« previous php.general (#327503) next »