Re: Find keys in multidimensional array

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx> 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@xxxxxxxxx> 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.

[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux