递归如果标量,数组
我有一些默认配置,以及一些可配置的特定配置。 我需要将特定配置合并到默认配置中。
value
标量的情况下,应该应用特定的配置 value
标量数组的情况下,应该合并数组并应用array_unique。 value
关联数组的情况下,我们需要应用上面的scalar
和scalar_array
规则。 例:
$defaultConfigs = [
'scalar1' => 1,
'scalar2' => "Apple",
'array_scalar' => [3,4,5],
'array_associative' => [
'scalar' => 1,
'array_scalar' => [1,2,3],
'array_associative' => [
...
]
],
];
$specificConfigs = [
'scalar1' => "A",
'array_scalar' => [3,4,5],
'array_associative' => [
'scalar' => 1,
'array_scalar' => [1,2,3],
'array_associative' => [
...
]
],
];
预期产出:
$expectedConfigs = [
'scalar1' => "A", // Overridden
'scalar2' => "Apple", // Default used
'array_scalar' => [1,2,3,4,5], // Scalar merged and array_unique
'array_associative' => [
'scalar' => "B", // Overridden
'array_scalar' => [1,2,3,4,5], // Scalar merged and array_unique
'array_associative' => [
...
]
],
];
有没有一个很好的干净方式来实现这一目标?
该功能可以获得您想要的结果。 它假定特定类型是默认类型的一致性,所以不执行一致性检查。 该函数迭代特定的配置数组并检查相应的默认值1:如果它是标量,则替换默认值; 如果它是一个枚举数组2,它将合并唯一值; 否则函数以当前值作为参数调用自身。
function fillConfig( $default, $specific )
{
foreach( $specific as $key=> $val )
{
if( isset( $default[$key] ) )
{
if( ! is_array( $default[$key] ) )
{
$default[$key] = $val;
}
elseif( array_keys($default[$key]) === range(0, count($default[$key]) - 1) )
{
$default[$key] = array_unique( array_merge( $default[$key], $val ) );
}
else
{
$default[$key] = fillConfig( $default[$key], $val );
}
}
else
{
// This happens when a specific key doesn't exists in default configuration.
// I think that in this case the value must be omitted,
// otherwise you can un-comment following line:
// $default[$key] = $val;
}
}
return $default;
}
以这种方式调用函数:
$result = fillConfig( $defaultConfigs, $specificConfigs );
$result
,应用于你的数组示例,是这样的:
Array
(
[scalar1] => A
[scalar2] => Apple
[array_scalar] => Array
(
[0] => 3
[1] => 4
[2] => 5
)
[array_associative] => Array
(
[scalar] => 1
[array_scalar] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[array_associative] => Array
(
)
)
)
有了这个阵列夫妇:
$defaultConfigs = [
'scalar1' => 1,
'scalar2' => "Apple",
'array_scalar' => [3,4,5],
'array_associative' => [
'scalar' => 1,
'array_scalar' => [1,2,3],
'array_associative' => [
]
],
];
$specificConfigs = [
'scalar1' => "A",
'array_scalar' => [3,4,5],
'array_associative' => [
'scalar' => B,
'array_scalar' => [3,4,5],
'array_associative' => [
]
],
];
$result
是:
Array
(
[scalar1] => A
[scalar2] => Apple
[array_scalar] => Array
(
[0] => 3
[1] => 4
[2] => 5
)
[array_associative] => Array
(
[scalar] => B
[array_scalar] => Array
(
[0] => 1
[1] => 2
[2] => 3
[4] => 4
[5] => 5
)
[array_associative] => Array
(
)
)
)
笔记:
1是的,这有点不一致:我觉得更好地遍历特定的数组(不存在的项目保持不变),但在默认数组上执行值检查,即参考点。
2枚举/关联数组检查基于这个答案。
我的情况稍有不同,但可能有所帮助。 我需要替换数组上的标量和array_merge_recursive。
class ArrayUtil {
public static function mergeRecursive(array $array1, $array2) {
if($array2 && is_array($array2)) {
foreach($array2 as $key => $val2) {
if (is_array($val2) && (null!==($val1 = isset($array1[$key]) ? $array1[$key] : null)) && is_array($val1)) {
$array1[$key] = self::mergeRecursive($val1,$val2);
} else {
$array1[$key] = $val2;
}
}
}
return $array1;
}
}
我使用config数组重新编写了第一个答案中的函数:
private function mergeConfigs(array $configs): array
{
$default = array_shift($configs);
return array_reduce($configs, function (array $result, array $config) {
foreach ($config as $key => $val) {
if (!isset($result[$key]) || !is_array($result[$key])) {
$result[$key] = $val;
continue;
}
$result[$key] = array_keys($result[$key]) === range(0, count($result[$key]) - 1)
? array_unique(array_merge($result[$key], $val))
: $this->mergeConfigs([$result[$key], $val]);
}
return $result;
}, $default);
}
链接地址: http://www.djcxy.com/p/32163.html
上一篇: recursive if scalar, array
下一篇: Publish a single iOS message to multiple AWS SNS Topics