2012-10-04 16 views
18

¿Cómo puedo hacer una extensión profunda de una matriz asociativa multidimensional (para usar con objetos JSON descodificados). Necesito el equivalente php de jQuery's $.extend(true, array1, array2) con matrices en lugar de JSON y en PHP.PHP Arreglo de extensión profunda

He aquí un ejemplo de lo que necesito (no parecía array_merge_recursive a hacer lo mismo)

$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')) 

Observe cómo matriz2 Array1 anula si tiene mismo valor (como cómo funciona la extensión de las clases)

+0

Por qué no array_merge? – Dev

+2

Si tiene PHP 5.3.0+, puede usar ['array_replace_recursive'] (http://www.php.net/manual/en/function.array-replace-recursive.php) que hace exactamente lo que necesita. – Sathvik

+0

No he tenido tiempo para revisar todas las respuestas pero array_replace_recursive definitivamente parece ser la forma más sencilla de lograr esto. ¿Quieres escribirlo como respuesta y lo acepto? –

Respuesta

18

Si tiene 5.3.0+ PHP, puede utilizar array_replace_recursive que hace exactamente lo que necesita:

array_replace_recursive() reemplaza los valores de matriz1 con los mismos valores de todas las las siguientes matrices. Si existe una clave del primer conjunto en el segundo conjunto, su valor se reemplazará por el valor del segundo conjunto. Si la clave existe en la segunda matriz, y no en la primera, se creará en la primera matriz. Si solo existe una clave en la primera matriz, se dejará tal cual. Si varias matrices están aprobadas para su reemplazo, se procesarán en orden, y la última matriz sobrescribirá los valores anteriores.

1

Tomado de 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

Esto debería ser Wiki Post –

+0

@Mihai Iorga Pregunta rápida, ¿cómo se hace una publicación wiki? – Baba

+1

@Baba Mientras edita/publica puede marcar "community" en alguna parte. – Yoshi

0

Con un poco de google he encontrado esto:

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

Esto podría ser lo que estás buscando:

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

Uso:

$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 
0

supongo que aquí es la respuesta correcta, debido a que:

  • su respuesta tiene un error con la advertencia:

    Advertencia: No se puede utilizar un valor escalar como una matriz en ...

Debido $ a no es siempre una matriz y que utilice un $ [$ k].

  • array_merge_recursive en efecto de combinación de arrays, pero convierte los valores con duplicados de las llaves a las matrices en lugar de sobrescribir el valor en la primera matriz con el valor duplicado en la segunda matriz, como array_merge hace.

  • otras torres no son recursivas ni simples.

lo tanto, aquí está mi respuesta: la respuesta sin errores:

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

Y mi respuesta con el operador ternario:

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

Editar: Y un bono que tiene el mayor número de matrices que desee:

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

yo uso esta en la misma forma en que uso angular.extend (dst, src) y 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); 
} 

Ejemplo:

Si() es una función esterilice utilidad que agarra $ _POST o $ _GET y devuelve una matriz.

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

Deberá utilizar: 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; 
}