PHP array_replace_recursive 如果是标量,array_merge_recursive 如果是数组

标签 php arrays recursion array-merge scalar

我有一些默认配置,以及一些可配置的特定配置。我需要将特定配置合并到默认配置中。

  • 在特定配置选项不存在的情况下,
    将使用默认选项。
  • value 的情况下是标量,具体配置应该应用
  • value 的情况下是标量数组,应合并数组并应用 array_unique。
  • value 的情况下是一个关联数组,我们需要应用上面的scalarscalar_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:如果是标量,则替换默认值;如果是枚举的array2,则合并唯一值;否则函数以当前值作为参数调用自身。

    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 枚举/关联数组检查基于 this answer .

    关于PHP array_replace_recursive 如果是标量,array_merge_recursive 如果是数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35552679/

    相关文章:

    arrays - 从 Scala 中的 for 循环生成 ArrayBuffer(或其他可变 Collection 类型)

    javascript - 未命名函数 JavaScript 的递归函数调用

    java - 递归斐波那契数列打印列表

    php - 文件上传到服务器上的文件夹,但数据库表更新时没有 SQL 注入(inject)?

    php - 如何仅对分支中已更改的文件进行 lint 或静态分析?

    javascript - 使用phonegap将图像上传到网络服务器的问题

    java - 如何跨递归堆栈处理同一数组(或 : How to pass a partial solution to the previous/next recursive call to method)

    c - 如何将 3d 指针数组传递给 c 中的函数?

    c 递归太深

    javascript - 我如何使用 PHP 读取/解析 javascript 的对象列表?