PHP Deep Extend Array

后端 未结 7 1415
遇见更好的自我
遇见更好的自我 2020-12-31 01:53

How can I do a deep extension of a multi dimensional associative array (for use with decoded JSON objects). I need the php equivalent of jQuery\'s $.extend(true, array1, arr

相关标签:
7条回答
  • 2020-12-31 02:01

    If you have PHP 5.3.0+, you can use array_replace_recursive which does exactly what you need:

    array_replace_recursive() replaces the values of array1 with the same values from all the following arrays. If a key from the first array exists in the second array, its value will be replaced by the value from the second array. If the key exists in the second array, and not the first, it will be created in the first array. If a key only exists in the first array, it will be left as is. If several arrays are passed for replacement, they will be processed in order, the later array overwriting the previous values.

    0 讨论(0)
  • 2020-12-31 02:02

    Taken from array_merge docs:

    function array_extend($a, $b) {
        foreach($b as $k=>$v) {
            if( is_array($v) ) {
                if( !isset($a[$k]) ) {
                    $a[$k] = $v;
                } else {
                    $a[$k] = array_extend($a[$k], $v);
                }
            } else {
                $a[$k] = $v;
            }
        }
        return $a;
    }
    
    0 讨论(0)
  • 2020-12-31 02:02

    I guess here is the correct answer, because:

    • your answer have a bug with warning:

      Warning: Cannot use a scalar value as an array in...

    Because $a is not always an array and you use $a[$k].

    • array_merge_recursive does indeed merge arrays, but it converts values with duplicate keys to arrays rather than overwriting the value in the first array with the duplicate value in the second array, as array_merge does.

    • other aswers are not recursives or not simple.

    So, here is my answer: your answer without bugs:

    function array_extend(array $a, array $b) {
        foreach($b as $k=>$v) {
            if( is_array($v) ) {
                if( !isset($a[$k]) ) {
                    $a[$k] = $v;
                } else {
                    if( !is_array($a[$k]){
                        $a[$k]=array();
                    }
                    $a[$k] = array_extend($a[$k], $v);
                }
            } else {
                $a[$k] = $v;
            }
        }
        return $a;
    }
    

    And my answer with ternary operator:

    function array_extend(array $a, array $b){
        foreach($b as $k=>$v)
                $a[$k] = is_array($v)&&isset($a[$k])?
                    array_extend(is_array($a[$k])?
                            $a[$k]:array(),$v):
                    $v;
        return $a;
    }
    

    Edit: And a bonus one with as many arrays you want:

    function array_extend(){
        $args = func_get_args();
        while($extended = array_shift($args))
                if(is_array($extended))
                        break;
        if(!is_array($extended))
                return FALSE;
        while($array = array_shift($args)){
            if(is_array($array))
                    foreach($array as $k=>$v)
                            $extended[$k] = is_array($v)&&isset($extended[$k])?
                                array_extend(is_array($extended[$k])?
                                        $extended[$k]:array(),$v):
                                $v;
        }
        return $extended;
    }
    
    0 讨论(0)
  • 2020-12-31 02:05

    I use this in the same way I use angular.extend(dst, src) and jQuery.extend().

    function extend($base = array(), $replacements = array()) {
        $base = ! is_array($base) ? array() : $base;
        $replacements = ! is_array($replacements) ? array() : $replacements;
    
        return array_replace_recursive($base, $replacements);
    }
    

    Example:

    si() is a utility sanitize function that grabs $_POST or $_GET and returns an array.

            $s = extend(array(
                'page' => 1,
                'take' => 100,
                'completed' => 1,
                'incomplete' => 1,
            ), si());
    
    0 讨论(0)
  • 2020-12-31 02:09

    You should use: https://github.com/appcia/webwork/blob/master/lib/Appcia/Webwork/Storage/Config.php#L64

    /**
     * Merge two arrays recursive
     *
     * Overwrite values with associative keys
     * Append values with integer keys
     *
     * @param array $arr1 First array
     * @param array $arr2 Second array
     *
     * @return array
     */
    public static function merge(array $arr1, array $arr2)
    {
        if (empty($arr1)) {
            return $arr2;
        } else if (empty($arr2)) {
            return $arr1;
        }
    
        foreach ($arr2 as $key => $value) {
            if (is_int($key)) {
                $arr1[] = $value;
            } elseif (is_array($arr2[$key])) {
                if (!isset($arr1[$key])) {
                    $arr1[$key] = array();
                }
    
                if (is_int($key)) {
                    $arr1[] = static::merge($arr1[$key], $value);
                } else {
                    $arr1[$key] = static::merge($arr1[$key], $value);
                }
            } else {
                $arr1[$key] = $value;
            }
        }
    
        return $arr1;
    }
    
    0 讨论(0)
  • 2020-12-31 02:15

    With a little googling I found this:

    /**
     * jquery style extend, merges arrays (without errors if the passed values are not arrays)
     *
     * @return array $extended
     **/
    function extend() {
        $args = func_get_args();
        $extended = array();
        if(is_array($args) && count($args)) {
            foreach($args as $array) {
                if(is_array($array)) {
                    $extended = array_merge($extended, $array);
                }
            }
        }
        return $extended;
    }
    
    extend($defaults, $new_options);
    
    0 讨论(0)
提交回复
热议问题