dotancohen
dotancohen

Reputation: 31491

Get path and value of all elements in nested associative array

Consider an associative array of arbitrary form and nesting depth, for example:

$someVar = array(
    'name'      => 'Dotan',
    'age'       => 35,
    'children'  => array(
        0 => array(
            'name'  => 'Meirav',
            'age'   => 6,
        ),
        1 => array(
            'name'  => 'Maayan',
            'age'   => 4,
        )
    ),
    'dogs' => array('Gili', 'Gipsy')
);

I would like to convert this to an associative array of paths and values:

$someVar = array(
    'name'            => 'Dotan',
    'age'             => 35,
    'children/0/name' => 'Meirav',
    'children/0/age'  => 6,
    'children/1/name' => 'Maayan',
    'children/1/age'  => 4,
    'dogs/0'          => 'Gili',
    'dogs/1'          => 'Gipsy'
);

I began writing a recursive function which for array elements would recurse and for non-array elements (int, floats, bools, and strings) return an array $return['path'] and $return['value']. This got sloppy quick! Is there a better way to do this in PHP? I would assume that callables and objects would not be passed in the array, though any solution which deals with that possibility would be best. Also, I am assuming that the input array would not have the / character in an element name, but accounting for that might be prudent! Note that the input array could be nested as deep as 8 or more levels deep!

Upvotes: 2

Views: 2780

Answers (2)

Jacob S
Jacob S

Reputation: 1701

Recursion is really the only way you'll be able to handle this, but here's a simple version to start with:

function nested_values($array, $path=""){
    $output = array();
    foreach($array as $key => $value) {
        if(is_array($value)) {
            $output = array_merge($output, nested_values($value, (!empty($path)) ? $path.$key."/" : $key."/"));
        }
        else $output[$path.$key] = $value;
    }
    return $output;
}

Upvotes: 4

kcsoft
kcsoft

Reputation: 2947

function getRecursive($path, $node) {
    if (is_array($node)) {
        $ret = '';
        foreach($node as $key => $val)
            $ret .= getRecursive($path.'.'.$key, $val);
        return $ret;
    }
    return $path.' => '.$node."\n";
}
$r = getRecursive('', $someVar);
print_r($r);

All yours to place it in an array.

Upvotes: 1

Related Questions