Подтвердить что ты не робот

PHP Deep Extend Array

Как я могу сделать глубокое расширение многомерного ассоциативного массива (для использования с декодированными объектами JSON). Мне нужен php-эквивалент jQuery $.extend(true, array1, array2) с массивами вместо JSON и PHP.

Вот пример того, что мне нужно (array_merge_recursive, похоже, не делает то же самое)

$array1 = ('1'=> ('a'=>'array1a', 'b'=>'array1b'));
$array2 = ('1'=> ('a'=>'array2a', 'c'=>'array2b'));

$array3 = array_extend($array1, $array2);

//$array3 = ('1'=> ('a'=>'array2a', 'b'=>'array1b', 'c'=>'array2b'))

Обратите внимание, как array2 переопределяет массив1, если он имеет такое же значение (например, как работает расширение классов)

4b9b3361

Ответ 1

Если у вас есть PHP 5.3.0+, вы можете использовать array_replace_recursive, который делает именно то, что вам нужно:

array_replace_recursive() заменяет значения array1 тем же значения из всех следующих массивов. Если ключ из первого массива существует во втором массиве, его значение будет заменено значением из второго массива. Если ключ существует во втором массиве, а не во-первых, он будет создан в первом массиве. Если ключ существует только в первом массиве он будет оставлен как есть. Если несколько массивов переданы для замены, они будут обработаны по порядку, позднее массив, перезаписывающий предыдущие значения.

Ответ 2

Я использую это так же, как я использую angular.extend(dst, src) и 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);
}

Пример:

si() - это функция sanitize, которая захватывает $_POST или $_GET и возвращает массив.

        $s = extend(array(
            'page' => 1,
            'take' => 100,
            'completed' => 1,
            'incomplete' => 1,
        ), si());

Ответ 3

Взято из 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;
}

Ответ 4

Это может быть то, что вы ищете:

function array_extend(&$result) {
  if (!is_array($result)) {
    $result = array();
  }

  $args = func_get_args();

  for ($i = 1; $i < count($args); $i++) {
    // we only work on array parameters:
    if (!is_array($args[$i])) continue;

    // extend current result:
    foreach ($args[$i] as $k => $v) {
      if (!isset($result[$k])) {
        $result[$k] = $v;
      }
      else {
        if (is_array($result[$k]) && is_array($v)) {
          array_extend($result[$k], $v);
        }
        else {
          $result[$k] = $v;
        }
      }
    }
  }

  return $result;
}

Использование:

$arr1 = array('a' => 1, 'b' => 2, 'c' => 3);
$arr2 = array('b' => 'b', 'd' => 'd');
array_extend($arr1, $arr2);
print_r($arr1); // array('a' => 1, 'b' => 'b', 'c' => 3, 'd' => 'd')

// or, to create a new array and leave $arr1 unchanged use:
array_extend($arr3, $arr1, $arr2);
print_r($arr3); // array('a' => 1, 'b' => 'b', 'c' => 3, 'd' => 'd')

// or, use the return value:
print_r(array_extend($arr1, $arr2)); // but this will also modify $arr1

Ответ 5

Вы должны использовать: 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;
}

Ответ 6

С небольшой поисковой системой я нашел это:

/**
 * 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);

Ответ 7

Я думаю, это правильный ответ, потому что:

  • у вашего ответа есть ошибка с предупреждением:

    Предупреждение: нельзя использовать скалярное значение в качестве массива в...

Поскольку $a не всегда является массивом, и вы используете $a [$ k].

  • array_merge_recursive действительно объединяет массивы, но преобразует значения с повторяющимися ключами в массивы, а не перезаписывает значение в первом массиве с дублирующимся значением во втором массиве, как это делает array_merge.

  • другие aswers не рекурсивные или не простые.

Итак, вот мой ответ: ваш ответ без ошибок:

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;
}

И мой ответ с тройным оператором:

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;
}

Изменить: и бонус с таким количеством массивов, которое вы хотите:

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;
}