Walk array recursively and print the path of the walk

前端 未结 9 1469
礼貌的吻别
礼貌的吻别 2020-12-03 08:03

Can someone help me with some code or instructions on how to walk recursively an array and when reaching the last element print the full path to it? A simple echo will work

相关标签:
9条回答
  • 2020-12-03 08:44

    I had similar problem. Here is a Depth-First Search-ish solution(no path depth included, it reaches until the very end of the array). Comment the 'if' statement if u don't want to include the value:

    $output = array();
    retrievePath($someArray, $output);
    
    function retrievePath($someArray, array &$pathKeeper)
    {
        if(!is_array($someArray)){ // $someArray == "end"
            $element = array_pop($pathKeeper) ?? '';// if the array is empty pop returns null, we don't want that
            array_push($pathKeeper, $element . '->'. $someArray);
        } else{
            end($someArray);//we want to get the last element from the array so we move the internal pointer to it's end
            $endElKey = key($someArray);//take the key where the pointer is
            reset($someArray);
            foreach($someArray as $key=>$value){
                $element = array_pop($pathKeeper);
                array_push($pathKeeper, $element === null ? $key : $element . '->' . $key);// we don't want '->' at the beginning
                retrievePath($value, $pathKeeper);
                if($key != $endElKey) //we check whether this is not the last loop
                    array_push($pathKeeper, $element);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-03 08:44

    I came up with the following function based on @salathe's one. It returns an array where each element is an array containing the leaf at index 0 and the array of the path keys at index 1:

    function loosenMultiDimensionalArrayPathForEachVal($array) {
        $iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array), \RecursiveIteratorIterator::SELF_FIRST);        
        $iterator->rewind();
        $res = [];
        foreach ($iterator as $v) {
            $depth = $iterator->getDepth();
            for ($path = array(), $i = 0, $z = $depth; $i <= $z; $i++) {
                $path[] = $iterator->getSubIterator($i)->key();
            }
            $leaf = $array;
            foreach ($path as $pathKey) {
                $leaf = $leaf[$pathKey];
            }
            if (!is_array($leaf)) {
                $res[] = [
                    $v,
                    $path
                ];
            }
        }
        return $res;
    }
    

    The main reason I implemented this one is that $iterator->hasChildren() returns true if the current iterated leaf is an object. Therefore, I wouldn't be able to get the path of it that way.

    0 讨论(0)
  • 2020-12-03 08:51

    You could employ a RecursiveIteratorIterator (docs) to take the hard work out of recursing through the arrays.

    function listArrayRecursive($someArray) {
        $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($someArray), RecursiveIteratorIterator::SELF_FIRST);
        foreach ($iterator as $k => $v) {
            $indent = str_repeat('&nbsp;', 10 * $iterator->getDepth());
            // Not at end: show key only
            if ($iterator->hasChildren()) {
                echo "$indent$k :<br>";
            // At end: show key, value and path
            } else {
                for ($p = array(), $i = 0, $z = $iterator->getDepth(); $i <= $z; $i++) {
                    $p[] = $iterator->getSubIterator($i)->key();
                }
                $path = implode(',', $p);
                echo "$indent$k : $v : path -> $path<br>";
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题