2012-10-04 14 views
18

Come posso eseguire un'estensione profonda di un array associativo multidimensionale (da utilizzare con oggetti JSON decodificati). Ho bisogno dell'equivalente php di jQuery's $.extend(true, array1, array2) con matrici invece di JSON e in PHP.PHP Deep Extend Array

Ecco un esempio di quello che mi serve (array_merge_recursive non sembra fare la stessa cosa)

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

Notate come array2 sostituzioni Array1 se ha lo stesso valore (come il funzionamento di estensione delle classi)

+0

Perché non array_merge? – Dev

+2

Se hai PHP 5.3.0+, puoi usare ['array_replace_recursive'] (http://www.php.net/manual/en/function.array-replace-recursive.php) che fa esattamente ciò di cui hai bisogno. – Sathvik

+0

Non ho ancora avuto il tempo di rivedere tutte le risposte, ma array_replace_recursive sembra decisamente il modo più semplice per farlo. Vuoi scriverlo come risposta e accetterò? –

risposta

18

Se avete PHP 5.3.0+, è possibile utilizzare array_replace_recursive che fa esattamente quello che vi serve:

array_replace_recursive() sostituisce i valori di array1 con gli stessi valori da tutto i seguenti array. Se una chiave del primo array esiste nel secondo array, il suo valore verrà sostituito dal valore dal secondo array. Se la chiave esiste nel secondo array e non è il il primo, verrà creato nel primo array. Se una chiave esiste solo nel primo array, verrà lasciata così com'è. Se diversi array sono stati sostituiti con lo per la sostituzione, verranno elaborati in ordine, la successiva matrice sovrascrivendo i valori precedenti.

1

Tratto da 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

Questo dovrebbe essere Wiki Post –

+0

@Mihai Iorga Domanda veloce come si fa un post wiki ??? – Baba

+1

@Baba Durante la modifica/pubblicazione è possibile controllare "comunità" da qualche parte. – Yoshi

0

Con un po 'googling ho trovato questo:

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

Questo potrebbe essere quello che stai cercando:

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

Usage:

$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

Credo che qui è la risposta corretta, perché:

  • la tua risposta ha un bug con avviso:

    Attenzione: non è possibile utilizzare un valore scalare come un array in ...

Perché $ a non è sempre una matrice e si utilizza $ a [$ k].

  • array_merge_recursive effettivamente unione matrici, ma converte valori con chiavi duplicate agli array anziché sovrascrivere il valore del primo array con il valore duplicato nella seconda matrice, come array_merge fa.

  • altri aswers non sono ricorsivi o non sono semplici.

Quindi, ecco la mia risposta: la risposta senza bug:

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

E la mia risposta con operatore 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; 
} 

Edit: E un bonus quella con il maggior numero di array vuoi:

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

Io uso questo nello stesso modo io uso angular.extend (dst, src) e 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); 
} 

Esempio:

si() è una funzione di utilità disinfettare che afferra $ _POST o $ _GET e restituisce un array.

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

Si dovrebbe usare: 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; 
}