Here is an example array:
$foo = array(
\'employer\' => array(
\'name\' => \'Foobar Inc\',
\'phone\
Here is a function which allows you to specify a top-level prefix via the second parameter:
function flatten_array($array, $prefix = null) {
if ($prefix) $prefix .= '_';
$items = array();
foreach ($array as $key => $value) {
if (is_array($value))
$items = array_merge($items, flatten_array($value, $prefix . $key));
else
$items[$prefix . $key] = $value;
}
return $items;
}
After a few iterations, I've been able to refine a solution to this problem that uses a stack-based approach to avoid recursion, simplifying things a bit.
/***
* @name array_flatten
* @author Tom Penzer @tpenzer
* Flattens a multi-tiered array into a single-tiered
* associative array with keys reflective of their
* values' hierarchy.
*
* @param array $array Required - the multi-
* level keyed array to be flattened
* @param string $separator Optional - the string
* used to separate the keys from different levels of
* the hierarchy
*
* @return array a single-level keyed array
***/
function array_flatten($array, $separator = '_') {
$output = array();
while (list($key, $value) = each($array)) {
if (is_array($value)) {
$build = array();
foreach ($value as $s_key => $s_value) {
$build[$key . $separator . $s_key] = $s_value;
}
unset($array[$key]);
$array = $build + $array;
unset($build);
continue;//skip write to $output
}
$output[$key] = $value;
unset($array[$key]);
}
return $output;
}
Not exactly the method requested, but it's a nice contrast to the recursive approaches to the problem.
This will flatten a multidimensional associative array tacking a digit to the key if its a duplicate. If you don't mind having a digit index to differentiate duplicate keys instead of concatenated keys this could be a solution.
$result = array();
array_walk_recursive($your_array, function($v, $k) use (&$result){ $i = ""; for (; isset($result[$k."$i"]); $i++); $result[$k."$i"] = $v; });
I suspect it could be worked on further to do concatenated keys.
The above solution is basically for doing this kind of thing
<?php
$xml_str = "
<images>
<image>
<position>0</position>
</image>
<image1>
<position>10</position>
</image1>
</images>";
// turn the xml into a multidimentional array
$ob = simplexml_load_string($xml_str);
$json = json_encode($ob);
$my_array = json_decode($json, true);
print_r($my_array);
// flatten it
$result = array();
array_walk_recursive($my_array, function($v, $k) use (&$result){ $i = ""; for (; isset($result[$k."$i"]); $i++); $result[$k."$i"] = $v; });
print_r($result);
?>
I think this 'trick' using is http_build_query is less of an eyesore w/out recursion (or at least letting php do it for you)
3 lines of code if your str_replace uses the url-encoded values for [ and ]
$string = http_build_query($array);
$string = urldecode($string);
$string = str_replace(
array('[',']'),
array('_','') ,
$string
);
parse_str($string, $flat_array);
$flat_array becomes :
array(7) {
["employer_name"] =>"Foobar Inc"
["employer_phone"] =>"555-555-5555"
["employee_name"] =>"John Doe"
["employee_phone"] =>"555-555-5556"
["employee_address_state"]=>"California"
["employee_address_zip"] =>"90210"
["modified"] =>"2009-12-01"
}
Something like this:
function makeNonNestedRecursive(array &$out, $key, array $in){
foreach($in as $k=>$v){
if(is_array($v)){
makeNonNestedRecursive($out, $key . $k . '_', $v);
}else{
$out[$key . $k] = $v;
}
}
}
function makeNonNested(array $in){
$out = array();
makeNonNestedRecursive($out, '', $in);
return $out;
}
// Example
$fooCompressed = makeNonNested($foo);
A solution whith only array_* php functions + recursive :
$array = array(
"level1"=>"value",
"level2" => ["level11" => "value", "level21" => "value"],
"level3" => ["level2" => ["level1" => "value"]],
"level4" => ["level3" => ["level2" => ["level1" => "value"]]],
"level5" => ["level4" => ["level3" => ["level2" => ["level1" => "value"]]]],
);
//flatten array with combined keys
function arrayFlat($array) {
$result = [];
array_walk($array, function($v, $pk)use(&$result){
if(is_array($v)) {
$result += arrayFlat(array_combine(
array_map(function($k) use($pk){ return $pk . '_' .$k; }, array_keys($v)),
$v
));
} else {
$result[$pk] = $v;
}
});
return $result;
}
print_r(arrayFlat($array));
Output :
Array
(
[level1] => value
[level2_level11] => value
[level2_level21] => value
[level3_level2_level1] => value
[level4_level3_level2_level1] => value
[level5_level4_level3_level2_level1] => value
)