从 php 中的数组生成多维数组?
Generate multi-dimensional array from an array in php?
我有一个关联数组列表如下:
[
"country" => "AU",
"state" => "VIC",
"suburb" => "Carlton",
"precedence" => ["country", "state", "suburb"]
]
我想要一个新的多维数组,如下所示,其中元素根据第一个数组上的 precedence 键定义的顺序嵌套:
[
"country" => [
"AU" => [
"state" => [
"VIC" => [
"suburb" => "Carlton
]
]
]
]
]
以上只是一个示例,我想要一个适用于任何类型数组的通用解决方案。所有输入数组都满足的唯一条件是它们将具有 precedence 元素,表示需要生成输出数组的顺序。
我已经尝试了一些递归解决方案,但它没有按预期工作,我遇到了 PHP 致命错误:允许的 1073741824 字节内存大小已耗尽(看起来是 运行 无限):
function generateArray(&$array)
{
foreach ($array['precedence'] as $key => $property) {
if ($key == sizeof($array['precedence']) - 1) {
return [$property => $array[$property]];
} else {
return generateAssetConfig($array);
}
}
}
试试这个:
function generateNestedArray($arr) {
$precedence = $arr['precedence'];
$nestedArray = [];
for ($i = count($precedence)-1; $i >= 0; $i--) {
$key = $precedence[$i];
if (!$nestedArray) {
$nestedArray[$key] = $arr[$key];
} else {
$nestedArray = [$key => [ $arr[$key]=> $nestedArray]];
}
}
return $nestedArray;
}
最简单的解决方案(递归函数):
function generateArrayRecursion($array, $precedenceIndex = 0) {
$precedence = $array['precedence'];
return [
$precedence[$precedenceIndex] => $precedenceIndex === \count($precedence) - 1
? $array[$precedence[$precedenceIndex]]
: [$array[$precedence[$precedenceIndex]] => generateArrayRecursion($array, $precedenceIndex + 1)]
];
}
备选方案(循环和数组引用):
function generateArray($array) {
$precedence = $array['precedence'];
$result = [];
$lastKey = $precedence[count($precedence) - 1];
$currentElement = &$result;
foreach ($precedence as $key) {
if ($key === $lastKey) {
$currentElement[$key] = $array[$key];
} else {
$currentElement[$key] = [$array[$key] => []];
$currentElement = &$currentElement[$key][$array[$key]];
}
}
return $result;
}
用法示例:
$array = [
"country" => "AU",
"state" => "VIC",
"suburb" => "Carlton",
"precedence" => ["country", "state", "suburb"]
];
var_dump(generateArrayRecursion($array));
var_dump(generateArray($array));
这是执行此操作的递归算法:
<?php
$raw = [
[
"country" => "AU",
"state" => "VIC",
"suburb" => "Carlton",
"precedence" => ["country", "state", "suburb"]
],
[
"country" => "AU",
"state" => "NSW",
"suburb" => "Sydney",
"precedence" => ["country", "state", "suburb"]
]
];
function generateFromPrecedence($array)
{
if (!isset($array['precedence']))
throw new Exception('Precedence array does not exist');
if (!empty(array_diff($array['precedence'], array_diff(array_keys($array), ['precedence']))))
throw new Exception('Keys and precendence keys different');
return generateStructure($array);
}
function generateStructure($array, $precedence = 0)
{
if ($precedence == count($array['precedence'])-1)
return [$array['precedence'][$precedence] => $array[$array['precedence'][$precedence]]];
return [$array['precedence'][$precedence] => [$array[$array['precedence'][$precedence]] => generateStructure($array, ++$precedence)]];
}
$output = generateFromPrecedence($raw[0]);
var_dump($output);
输出:
array(1) {
["country"]=>
array(1) {
["AU"]=>
array(1) {
["state"]=>
array(1) {
["NSW"]=>
array(1) {
["suburb"]=>
string(6) "Sydney"
}
}
}
}
}
你可以循环前面部分的反转项。
如果结果数组中还没有项目,添加第一个键=>值对。
Else 将当前结果包装在一个多维数组中,将迭代的当前值设置为外键,并将该值(对于源数组中的该键)与当前结果一起包装在第二个数组中。
$source = [
"country" => "AU",
"state" => "VIC",
"suburb" => "Carlton",
"precedence" => ["country", "state", "suburb"]
];
function generateArray($array)
{
$result = [];
foreach(array_reverse($array["precedence"]) as $v) {
$result =! $result ? [$v => $array[$v]] : [$v => [$array[$v] => $result]];
}
return $result;
}
var_export(generateArray($source));
输出
array (
'country' =>
array (
'AU' =>
array (
'state' =>
array (
'VIC' =>
array (
'suburb' => 'Carlton',
),
),
),
),
)
我有一个关联数组列表如下:
[
"country" => "AU",
"state" => "VIC",
"suburb" => "Carlton",
"precedence" => ["country", "state", "suburb"]
]
我想要一个新的多维数组,如下所示,其中元素根据第一个数组上的 precedence 键定义的顺序嵌套:
[
"country" => [
"AU" => [
"state" => [
"VIC" => [
"suburb" => "Carlton
]
]
]
]
]
以上只是一个示例,我想要一个适用于任何类型数组的通用解决方案。所有输入数组都满足的唯一条件是它们将具有 precedence 元素,表示需要生成输出数组的顺序。
我已经尝试了一些递归解决方案,但它没有按预期工作,我遇到了 PHP 致命错误:允许的 1073741824 字节内存大小已耗尽(看起来是 运行 无限):
function generateArray(&$array)
{
foreach ($array['precedence'] as $key => $property) {
if ($key == sizeof($array['precedence']) - 1) {
return [$property => $array[$property]];
} else {
return generateAssetConfig($array);
}
}
}
试试这个:
function generateNestedArray($arr) {
$precedence = $arr['precedence'];
$nestedArray = [];
for ($i = count($precedence)-1; $i >= 0; $i--) {
$key = $precedence[$i];
if (!$nestedArray) {
$nestedArray[$key] = $arr[$key];
} else {
$nestedArray = [$key => [ $arr[$key]=> $nestedArray]];
}
}
return $nestedArray;
}
最简单的解决方案(递归函数):
function generateArrayRecursion($array, $precedenceIndex = 0) {
$precedence = $array['precedence'];
return [
$precedence[$precedenceIndex] => $precedenceIndex === \count($precedence) - 1
? $array[$precedence[$precedenceIndex]]
: [$array[$precedence[$precedenceIndex]] => generateArrayRecursion($array, $precedenceIndex + 1)]
];
}
备选方案(循环和数组引用):
function generateArray($array) {
$precedence = $array['precedence'];
$result = [];
$lastKey = $precedence[count($precedence) - 1];
$currentElement = &$result;
foreach ($precedence as $key) {
if ($key === $lastKey) {
$currentElement[$key] = $array[$key];
} else {
$currentElement[$key] = [$array[$key] => []];
$currentElement = &$currentElement[$key][$array[$key]];
}
}
return $result;
}
用法示例:
$array = [
"country" => "AU",
"state" => "VIC",
"suburb" => "Carlton",
"precedence" => ["country", "state", "suburb"]
];
var_dump(generateArrayRecursion($array));
var_dump(generateArray($array));
这是执行此操作的递归算法:
<?php
$raw = [
[
"country" => "AU",
"state" => "VIC",
"suburb" => "Carlton",
"precedence" => ["country", "state", "suburb"]
],
[
"country" => "AU",
"state" => "NSW",
"suburb" => "Sydney",
"precedence" => ["country", "state", "suburb"]
]
];
function generateFromPrecedence($array)
{
if (!isset($array['precedence']))
throw new Exception('Precedence array does not exist');
if (!empty(array_diff($array['precedence'], array_diff(array_keys($array), ['precedence']))))
throw new Exception('Keys and precendence keys different');
return generateStructure($array);
}
function generateStructure($array, $precedence = 0)
{
if ($precedence == count($array['precedence'])-1)
return [$array['precedence'][$precedence] => $array[$array['precedence'][$precedence]]];
return [$array['precedence'][$precedence] => [$array[$array['precedence'][$precedence]] => generateStructure($array, ++$precedence)]];
}
$output = generateFromPrecedence($raw[0]);
var_dump($output);
输出:
array(1) {
["country"]=>
array(1) {
["AU"]=>
array(1) {
["state"]=>
array(1) {
["NSW"]=>
array(1) {
["suburb"]=>
string(6) "Sydney"
}
}
}
}
}
你可以循环前面部分的反转项。
如果结果数组中还没有项目,添加第一个键=>值对。
Else 将当前结果包装在一个多维数组中,将迭代的当前值设置为外键,并将该值(对于源数组中的该键)与当前结果一起包装在第二个数组中。
$source = [
"country" => "AU",
"state" => "VIC",
"suburb" => "Carlton",
"precedence" => ["country", "state", "suburb"]
];
function generateArray($array)
{
$result = [];
foreach(array_reverse($array["precedence"]) as $v) {
$result =! $result ? [$v => $array[$v]] : [$v => [$array[$v] => $result]];
}
return $result;
}
var_export(generateArray($source));
输出
array (
'country' =>
array (
'AU' =>
array (
'state' =>
array (
'VIC' =>
array (
'suburb' => 'Carlton',
),
),
),
),
)