Re: Find keys in multidimensional array
[email protected] (Glash Gnome)
| Newsgroups | php.general |
|---|---|
| Message-ID | <CADeZBNaKqxkrTo0UzN8iAJJRrwHmTycvsiV2j8g+m4cLS9y4SQ@mail.gmail.com> |
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 <
[email protected]> 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 <[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.
>>
>