Here is an example array:
下面是一个示例数组:
$foo = array(
'employer' => array(
'name' => 'Foobar Inc',
'phone' => '555-555-5555'
),
'employee' => array(
'name' => 'John Doe',
'phone' => '555-555-5556',
'address' => array(
'state' => 'California',
'zip' => '90210'
)
),
'modified' => '2009-12-01',
);
And I would like to get a result like this:
我想得到这样的结果:
$fooCompressed = array(
'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'
)
How would I go about writing a recursive function to handle this?
我该如何写一个递归函数来处理这个呢?
5 个解决方案
#1
14
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);
#2
3
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;
}
#3
3
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)
我认为这种使用http_build_query的“技巧”不太会影响w/out递归(或者至少让php为您做)
3 lines of code if your str_replace uses the url-encoded values for [ and ]
如果str_replace使用的是url编码的值,那么3行代码
$string = http_build_query($array);
$string = urldecode($string);
$string = str_replace(
array('[',']'),
array('_','') ,
$string
);
parse_str($string, $flat_array);
$flat_array becomes :
美元flat_array就变成:
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"
}
#4
0
/**
* Flatten a multi-dimensional array or a nested object, constructing concatenated keys for
* nested elements.
* @param array or object $array - the array or object to be flattened
* @param array or string $key_path - current parent keys path.
* Pass this parameter as string if you need to set a common prefix for all keys
* @param string $level_separator - keys concatenation glue
* @param array $flat - resulting flattened array (omit this parameter when calling the function)
* @return single-dimensional array with all array keys as concatenated keys of elements'
* paths through the data structure
*/
function flattenArray($array, &$key_path = array(), $level_separator = '.', &$flat = array())
{
if(!is_array($key_path))
{
// sanitize key_path
$key_path = array((string)$key_path);
}
foreach($array as $key => $value)
{
// push current key to path
array_push($key_path, $key);
if(is_array($value) || is_object($value))
{
// next level recursion
$flat = array_merge($flat, flattenArray($value, $key_path, $level_separator, $flat));
}
else
{
// write the value directly
$flat[implode($level_separator, $key_path)] = $value;
}
// remove used key
array_pop($key_path);
}
return $flat;
}
#5
0
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.
不完全是所请求的方法,但与递归方法相比,这是一个很好的对比。
#1
14
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);
#2
3
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;
}
#3
3
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)
我认为这种使用http_build_query的“技巧”不太会影响w/out递归(或者至少让php为您做)
3 lines of code if your str_replace uses the url-encoded values for [ and ]
如果str_replace使用的是url编码的值,那么3行代码
$string = http_build_query($array);
$string = urldecode($string);
$string = str_replace(
array('[',']'),
array('_','') ,
$string
);
parse_str($string, $flat_array);
$flat_array becomes :
美元flat_array就变成:
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"
}
#4
0
/**
* Flatten a multi-dimensional array or a nested object, constructing concatenated keys for
* nested elements.
* @param array or object $array - the array or object to be flattened
* @param array or string $key_path - current parent keys path.
* Pass this parameter as string if you need to set a common prefix for all keys
* @param string $level_separator - keys concatenation glue
* @param array $flat - resulting flattened array (omit this parameter when calling the function)
* @return single-dimensional array with all array keys as concatenated keys of elements'
* paths through the data structure
*/
function flattenArray($array, &$key_path = array(), $level_separator = '.', &$flat = array())
{
if(!is_array($key_path))
{
// sanitize key_path
$key_path = array((string)$key_path);
}
foreach($array as $key => $value)
{
// push current key to path
array_push($key_path, $key);
if(is_array($value) || is_object($value))
{
// next level recursion
$flat = array_merge($flat, flattenArray($value, $key_path, $level_separator, $flat));
}
else
{
// write the value directly
$flat[implode($level_separator, $key_path)] = $value;
}
// remove used key
array_pop($key_path);
}
return $flat;
}
#5
0
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.
不完全是所请求的方法,但与递归方法相比,这是一个很好的对比。