2009-02-08 19 views
58

Probabilmente è una domanda per principianti, ma sto esaminando la documentazione già da molto tempo e non riesco a trovare alcuna soluzione. Ho pensato che avrei potuto usare implode per ogni dimensione e poi rimettere insieme quelle stringhe con str_split per creare un nuovo array semplice. Tuttavia non so mai se il pattern di join non è anche in valori e quindi dopo aver fatto str_split i miei valori originali potrebbero rompersi.Come "appiattire" un array multidimensionale a uno semplice in PHP?

C'è qualcosa come combine($array1, $array2) per gli array all'interno di un array multidimensionale?

+0

** Si prega di controllare questo link per soluzione **: http://stackoverflow.com/questions/14951811/i-want- to-add-sub-array-to-one-single-array-in-php/14952110 # 14952110 –

+1

** Un'altra buona domanda di riferimento ** con risposte forse migliori: [Come appiattire una matrice multidimensionale?] (http://stackoverflow.com/q/1319903/367456) – hakre

risposta

40

Use array_values. (Example from php site)

<?php 

$aNonFlat = array(
    1, 
    2, 
    array(
     3, 
     4, 
     5, 
     array(
      6, 
      7 
     ), 
     8, 
     9, 
    ), 
    10, 
    11 
); 

$objTmp = (object) array('aFlat' => array()); 

array_walk_recursive($aNonFlat, create_function('&$v, $k, &$t', '$t->aFlat[] = $v;'), $objTmp); 

var_dump($objTmp->aFlat); 

/* 
array(11) { 
    [0]=> 
    int(1) 
    [1]=> 
    int(2) 
    [2]=> 
    int(3) 
    [3]=> 
    int(4) 
    [4]=> 
    int(5) 
    [5]=> 
    int(6) 
    [6]=> 
    int(7) 
    [7]=> 
    int(8) 
    [8]=> 
    int(9) 
    [9]=> 
    int(10) 
    [10]=> 
    int(11) 
} 
*/ 

?> 
+2

Grazie! Probabilmente dovrei controllare anche le note dell'utente la prossima volta. – Adriana

+0

Qualcuno sa perché questo non funziona a meno che non utilizzi la passata in fase di chiamata (ammortizzata) per riferimento. ovvero array_walk_recursive ($ array, create_function ('& $ v, $ k, & $ t', '$ t [] = $ v;'), e $ appiattito); La definizione della funzione è definita correttamente come passaggio per riferimento. ma non funziona a meno che non passi per riferimento durante le chiamate. – jskulski

+2

Gli oggetti @jskilski ('$ objTmp' in questo esempio) vengono passati automaticamente per riferimento; gli array non lo sono. Prova a utilizzare una funzione anonima (http://php.net/manual/en/functions.anonymous.php) invece di 'create_function'. – dave1010

3

Una soluzione non ricorsiva (ma ordine distruggendo):

function flatten($ar) { 
    $toflat = array($ar); 
    $res = array(); 

    while (($r = array_shift($toflat)) !== NULL) { 
     foreach ($r as $v) { 
      if (is_array($v)) { 
       $toflat[] = $v; 
      } else { 
       $res[] = $v; 
      } 
     } 
    } 

    return $res; 
} 
5
function flatten_array($array, $preserve_keys = 0, &$out = array()) { 
    # Flatten a multidimensional array to one dimension, optionally preserving keys. 
    # 
    # $array - the array to flatten 
    # $preserve_keys - 0 (default) to not preserve keys, 1 to preserve string keys only, 2 to preserve all keys 
    # $out - internal use argument for recursion 
    foreach($array as $key => $child) 
     if(is_array($child)) 
      $out = flatten_array($child, $preserve_keys, $out); 
     elseif($preserve_keys + is_string($key) > 1) 
      $out[$key] = $child; 
     else 
      $out[] = $child; 
    return $out; 
} 
+0

Scusa ma non sembra gestire correttamente gli array multidimensionali - [Demo] (https://3v4l.org/aRj32) –

17
// $array = your multidimensional array 

$flat_array = array(); 

foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $k=>$v){ 

$flat_array[$k] = $v; 

} 

anche documentato: http://www.phpro.org/examples/Flatten-Array.html

+2

Nota: utilizzare solo per matrici di primitivi. "RecursiveArrayIterator considera tutti gli oggetti come figli e tenta di ricorrere a loro". http://www.php.net/manual/en/class.recursivearrayiterator.php#106519 – ReactiveRaven

+2

C'è anche ['iterator_to_array'] (http://php.net/iterator_to_array) – hakre

+0

@hakre: +1 concordato: aggiunta 'iterator_to_array()' a questa risposta annullerebbe la necessità del ciclo 'foreach'. Potrebbe essere una semplice funzione one-liner. (anche se una linea piuttosto lunga) – SDC

1

Se you'r okay con la perdita dei tasti dell'array, puoi appiattire un array multidimensionale usando una chiusura ricorsiva come callback che utilizza array_values ​​(), assicurandoti che questo callback sia un parametro per array_walk(), come segue.

<?php 

$array = [1,2,3,[5,6,7]]; 
$nu_array = null; 
$callback = function ($item) use(&$callback, &$nu_array) { 
    if (!is_array($item)) { 
    $nu_array[] = $item; 
    } 
    else 
    if (is_array($item)) { 
    foreach(array_values($item) as $v) { 
     if (!(is_array($v))) { 
      $nu_array[] = $v; 
     } 
     else 
     { 
      $callback($v); 
     continue; 
     }  
    } 
    } 
}; 

array_walk($array, $callback); 
print_r($nu_array); 

L'unico inconveniente dell'esempio precedente è che coinvolge la scrittura molto più codice rispetto la seguente soluzione che utilizza array_walk_recursive() insieme con un callback semplificata:

<?php 

$array = [1,2,3,[5,6,7]]; 

$nu_array = []; 
array_walk_recursive($array, function ($item) use(&$nu_array) 
        { 
         $nu_array[] = $item; 
        } 
); 
print_r($nu_array); 

Vedi live code

Questo esempio sembra preferibile a quello precedente, nascondendo i dettagli su come vengono estratti i valori da una matrice multidimensionale. Sicuramente, l'iterazione si verifica, ma indipendentemente dal fatto che comporti ricorsione o struttura (i) di controllo, lo saprai solo dalla scansione di array.c. Poiché la programmazione funzionale si concentra sull'input e sull'output piuttosto che sulle minuzie per ottenere un risultato, sicuramente non si può preoccuparsi di come avviene l'iterazione dietro le quinte, cioè finché un datore di lavoro prospettico pone una domanda del genere.

5

Un altro metodo da PHP di user comments (semplificato) e here:

function array_flatten_recursive($array) { 
    if (!$array) return false; 
    $flat = array(); 
    $RII = new RecursiveIteratorIterator(new RecursiveArrayIterator($array)); 
    foreach ($RII as $value) $flat[] = $value; 
    return $flat; 
} 

Il grande vantaggio di questo metodo è che traccia la profondità della ricorsione, se avete bisogno che mentre appiattimento.
Questo stamperà:

$array = array( 
    'A' => array('B' => array(1, 2, 3)), 
    'C' => array(4, 5) 
); 
print_r(array_flatten_recursive($array)); 

#Returns: 
Array ( 
    [0] => 1 
    [1] => 2 
    [2] => 3 
    [3] => 4 
    [4] => 5 
) 
+3

Nota: utilizzare solo per matrici di primitivi. "RecursiveArrayIterator considera tutti gli oggetti come figli e tenta di ricorrere a loro". http://www.php.net/manual/en/class.recursivearrayiterator.php#106519 – ReactiveRaven

4

In PHP> = 5.3 e in base alla risposta di Luc M (il primo) si può fare uso di chiusure come questo

array_walk_recursive($aNonFlat, function(&$v, $k, &$t){$t->aFlat[] = $v;}, $objTmp); 

Amo questo perché non ho a circondare il codice della funzione con le citazioni, come quando si usa create_function()

+1

se stai usando le funzioni anonime, puoi usare una variabile di chiusura catturata direttamente piuttosto che questa roba 'objTemp' – user102008

+1

C'è un bug in PHP 5.3.3 che causa questo crash - https://bugs.php.net/bug.php?id=52719 – crazyphoton

1

Un nuovo approccio basato sulla funzione dell'esempio precedente Inserito da caos, che risolve il bug di overwritting chiavi stringa in multiarrays:

# Flatten a multidimensional array to one dimension, optionally preserving keys. 
# $array - the array to flatten 
# $preserve_keys - 0 (default) to not preserve keys, 1 to preserve string keys only, 2 to preserve all keys 
# $out - internal use argument for recursion 

function flatten_array($array, $preserve_keys = 2, &$out = array(), &$last_subarray_found) 
{ 
     foreach($array as $key => $child) 
     { 
      if(is_array($child)) 
      { 
       $last_subarray_found = $key; 
       $out = flatten_array($child, $preserve_keys, $out, $last_subarray_found); 
      } 
      elseif($preserve_keys + is_string($key) > 1) 
      { 
       if ($last_subarray_found) 
       { 
        $sfinal_key_value = $last_subarray_found . "_" . $key; 
       } 
       else 
       { 
        $sfinal_key_value = $key; 
       } 
       $out[$sfinal_key_value] = $child; 
      } 
      else 
      { 
       $out[] = $child; 
      } 
     } 

     return $out; 
} 

Example: 
$newarraytest = array(); 
$last_subarray_found = ""; 
$this->flatten_array($array, 2, $newarraytest, $last_subarray_found); 
1
/*consider $mArray as multidimensional array and $sArray as single dimensional array 
this code will ignore the parent array 
*/ 

function flatten_array2($mArray) { 
    $sArray = array(); 

    foreach ($mArray as $row) { 
     if (!(is_array($row))) { 
      if($sArray[] = $row){ 
      } 
     } else { 
      $sArray = array_merge($sArray,flatten_array2($row)); 
     } 
    } 
    return $sArray; 
} 
1

si può provare questo:

function flat_an_array($a) 
{ 
    foreach($a as $i) 
    { 
     if(is_array($i)) 
     { 
      if($na) $na = array_merge($na,flat_an_array($i)); 
      else $na = flat_an_array($i); 
     } 
     else $na[] = $i; 
    } 
    return $na; 
} 
102
$array = your array 

$result = call_user_func_array('array_merge', $array); 

echo "<pre>"; 
print_r($result); 

REF: http://php.net/manual/en/function.call-user-func-array.php

Ecco un'altra soluzione (funziona con array multi-dimensionale):

function array_flatten($array) { 

    $return = array(); 
    foreach ($array as $key => $value) { 
     if (is_array($value)){ $return = array_merge($return, array_flatten($value));} 
     else {$return[$key] = $value;} 
    } 
    return $return; 

} 

$array = Your array 

$result = array_flatten($array); 

echo "<pre>"; 
print_r($result); 
+5

Soluzione elegante, questa dovrebbe essere la risposta migliore. – Jonline

+2

Questa è la risposta più elegante al problema indicato. Thumbs up – user2831723

35

Questa è una riga, Super facile da usare:

$result = array(); 
array_walk_recursive($original_array,function($v, $k) use (&$result){ $result[] = $v; }); 

È molto facile da capire, all'interno della funzione anonima/chiusura $ v è il valore e $ k è la chiave della matrice originale.

+5

IMHO questa dovrebbe essere la migliore risposta. – Julian

+1

Questo è l'unico che ha funzionato per me in un array a due livelli. –

+1

questo merita più l'upvote – slier

0

Se siete interessati in appena i valori di una chiave particolare, si potrebbe trovare questo approccio utile:

function valuelist($array, $array_column) { 
    $return = array(); 
    foreach($array AS $row){ 
     $return[]=$row[$array_column]; 
    }; 
    return $return; 
}; 

Esempio:

Dato $ get_role_action =

array(3) { 
    [0]=> 
    array(2) { 
    ["ACTION_CD"]=> 
    string(12) "ADD_DOCUMENT" 
    ["ACTION_REASON"]=> 
    NULL 
    } 
    [1]=> 
    array(2) { 
    ["ACTION_CD"]=> 
    string(13) "LINK_DOCUMENT" 
    ["ACTION_REASON"]=> 
    NULL 
    } 
    [2]=> 
    array(2) { 
    ["ACTION_CD"]=> 
    string(15) "UNLINK_DOCUMENT" 
    ["ACTION_REASON"]=> 
    NULL 
    } 
} 

di $variables['role_action_list']=valuelist($get_role_action, 'ACTION_CD'); risulterebbe in:

$variables["role_action_list"]=> 
    array(3) { 
    [0]=> 
    string(12) "ADD_DOCUMENT" 
    [1]=> 
    string(13) "LINK_DOCUMENT" 
    [2]=> 
    string(15) "UNLINK_DOCUMENT" 
    } 

Da lì è possibile eseguire valore look-up in questo modo:

if(in_array('ADD_DOCUMENT', $variables['role_action_list'])){ 
    //do something 
}; 
+0

Questo è un knock-off PHP di una funzione CFML con lo stesso nome. –

3

con PHP 7, è possibile utilizzare i generatori e la delega del generatore (yield from) per appiattire un array:

function array_flatten_iterator (array $array) { 
    foreach ($array as $value) { 
     if (is_array($value)) { 
      yield from array_flatten_iterator($value); 
     } else { 
      yield $value; 
     } 
    } 
} 

function array_flatten (array $array) { 
    return iterator_to_array(array_flatten_iterator($array), false); 
} 

Esempio:

$array = [ 
    1, 
    2, 
    [ 
     3, 
     4, 
     5, 
     [ 
      6, 
      7 
     ], 
     8, 
     9, 
    ], 
    10, 
    11, 
];  

var_dump(array_flatten($array)); 

http://3v4l.org/RU30W

0

tutto ciò non ha funzionato per me ... così ho dovuto eseguirlo da solo. funziona bene:

function arrayFlat($arr){ 
$out = ''; 
    foreach($arr as $key => $value){ 

     if(!is_array($value)){ 
      $out .= $value.','; 
     }else{ 
      $out .= $key.','; 
      $out .= arrayFlat($value); 
     } 

    } 
    return trim($out,','); 
} 


$result = explode(',',arrayFlat($yourArray)); 
echo '<pre>'; 
print_r($result); 
echo '</pre>'; 
0

dato array multidimensionale e convertirlo in unidimensionale, può essere fatto da disinserire tutti i valori che stanno avendo array e li risparmio in prima dimensione, ad esempio:

function _flatten_array($arr) { 
    while ($arr) { 
    list($key, $value) = each($arr); 
    is_array($value) ? $arr = $value : $out[$key] = $value; 
    unset($arr[$key]); 
    } 
    return (array)$out; 
} 
2

utilizzando le funzioni di ordine superiore (Nota: sto usando inline anonymous functions, che è apparso in PHP 5.3):

function array_flatten($array) { 
    return array_reduce(
     $array, 
     function($prev, $element) { 
      if (!is_array($element)) 
       $prev[] = $element; 
      else 
       $prev = array_merge($prev, array_flatten($element)); 
      return $prev; 
     }, 
     array() 
    ); 
} 
0

È possibile utilizzare ilFunzioneda Non-standard PHP library (NSPL). Funziona con matrici e strutture di dati iterabili.

assert([1, 2, 3, 4, 5, 6, 7, 8, 9] === flatten([[1, [2, [3]]], [[[4, 5, 6]]], 7, 8, [9]])); 
0

semplice approach..See tramite ricorsione ..

<?php 

function flatten_array($simple){ 
static $outputs=array(); 
foreach ($simple as $value) 
{ 
if(is_array($value)){ 
    flatten_array($value); 
} 
else{ 
    $outputs[]=$value; 
} 

} 
return $outputs; 
} 

$eg=['s'=>['p','n'=>['t']]]; 
$out=flatten_array($eg); 
print_r($out); 

?> 
Problemi correlati