How do I recursively create a multidimensional array?
I am trying to create a multidimensional array whose parts are defined by a string. I use it .
as a separator and each part (except the last) should be an array
for example:
config.debug.router.strictMode = true
I need the same results as for input:
$arr = array('config' => array('debug' => array('router' => array('strictMode' => true))));
This issue really got me going in circles, any help is appreciated. Thank!
source to share
Suppose we already have a key and a value in $key
and $val
, then you can do this:
$key = 'config.debug.router.strictMode';
$val = true;
$path = explode('.', $key);
Building the array from left to right:
$arr = array();
$tmp = &$arr;
foreach ($path as $segment) {
$tmp[$segment] = array();
$tmp = &$tmp[$segment];
}
$tmp = $val;
And from right to left:
$arr = array();
$tmp = $val;
while ($segment = array_pop($path)) {
$tmp = array($segment => $tmp);
}
$arr = $tmp;
source to share
I say I split everything, start at the value and work back from there, each time through, wrapping what you have in another array. For example:
$s = 'config.debug.router.strictMode = true';
list($parts, $value) = explode(' = ', $s);
$parts = explode('.', $parts);
while($parts) {
$value = array(array_pop($parts) => $value);
}
print_r($parts);
Definitely rewrite it to have error checking.
source to share
Gumbo's answer looks good.
However, it looks like you want to parse a typical .ini file.
Consider using library code instead of rewinding your own.
For example, Zend_Config does a great job with this.
source to share
I really love that JasonWolf answers this.
As for possible mistakes: yes, but he gave a great idea, now the reader needs to make it bulletproof.
My need was a little simpler: from a delimited list, create an MD array. I modified his code slightly to give me exactly this. This version will give you an array with or without a definition string, or even a non-delimited string.
I hope someone can make it even better.
$parts = "config.debug.router.strictMode";
$parts = explode(".", $parts);
$value = null;
while($parts) {
$value = array(array_pop($parts) => $value);
}
print_r($value);
source to share
// The attribute to the right of the equals sign
$rightOfEquals = true;
$leftOfEquals = "config.debug.router.strictMode";
// Array of identifiers
$identifiers = explode(".", $leftOfEquals);
// How many 'identifiers' we have
$numIdentifiers = count($identifiers);
// Iterate through each identifier backwards
// We do this backwards because we want the "innermost" array element
// to be defined first.
for ($i = ($numIdentifiers - 1); $i >=0; $i--)
{
// If we are looking at the "last" identifier, then we know what its
// value is. It is the thing directly to the right of the equals sign.
if ($i == ($numIdentifiers - 1))
{
$a = array($identifiers[$i] => $rightOfEquals);
}
// Otherwise, we recursively append our new attribute to the beginning of the array.
else
{
$a = array($identifiers[$i] => $a);
}
}
print_r($a);
source to share