2

Given an array, I would like a flattened version of the array keys. Each array key would need the 'path' of the array, to that point, appended with an underscore.

An example explains this best.

$arr = array("location"=>0,"details"=>array("width"=>0,"height"=>0,"level"=>array("three"=>0)));

function answer($arr) {....}

the answer function would return this:

array("location","details_width","details_height","details_level_three");

UPDATE:

Here is the work in progress. It will accept an array and return the array keys, but with no depth:

function recursive_keys($input)
{
    $output = array_keys($input);
    foreach($input as $sub){
        if(is_array($sub)){
            $output = array_merge($output, recursive_keys($sub));
        }
    }
    return $output;
}
3
  • I have a set of functions that can successfully traverse a multidimensional array, and return all the array keys . But I don't know how to append the current 'path' as I am traversing the array. Commented Dec 5, 2011 at 22:21
  • well show your unsuccessffull attempts Commented Dec 5, 2011 at 22:22
  • original comment has been updated. Commented Dec 5, 2011 at 22:39

2 Answers 2

7
$ritit = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
$results = array();
foreach ($ritit as $leafValue) {
    $path = array();
    foreach (range(0, $ritit->getDepth()) as $depth) {
        $path[] = $ritit->getSubIterator($depth)->key();
    }
    $results[] = join('_', $path);
}
Sign up to request clarification or add additional context in comments.

2 Comments

+1 For the idea, anyway if you are dealing with empty arrays (as I did) this solution is not complete because the RecursiveArrayIterator cannot recognize the 'leaves'. To make it work with leaves array that are empty you can use a class similar to this: class RecursiveArrayOnlyIterator extends RecursiveArrayIterator { public function hasChildren() { return is_array($this->current()) && (count($this->current())>0); } } Reference: php.net
@AntonioE. you could also just use the RecursiveIteratorIterator::SELF_FIRST arg for the RecursiveIteratorIterator constructor(then it will visit all nodes, not just leaves). But, you will get many partial, less than full paths as a result.
2
function recursive_keys(array $array, array $path = array()) {
    $result = array();
    foreach ($array as $key => $val) {
        $currentPath = array_merge($path, array($key));
        if (is_array($val)) {
            $result = array_merge($result, recursive_keys($val, $currentPath));
        } else {
            $result[] = join('_', $currentPath);
        }
    }
    return $result;
}

Demo here: http://codepad.viper-7.com/WQ3UYI

3 Comments

Excellent, this is what I need! To your code, I added if(!is_array($val)) right before the if(!is_array($val)) line as I dont' want to add a key if it's value is an array.
I use if (is_array($val) && $val) instead of if (is_array($val)) to get it work in my case
@deceze this demo link has died. This answer could also use some explanation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.