Come appiattire una matrice multidimensionale?


259

È possibile, in PHP, appiattire un array (bi / multi) dimensionale senza ricorrere a ricorsioni o riferimenti?

Sono interessato solo ai valori, quindi le chiavi possono essere ignorate, sto pensando nelle righe di array_map()e array_values().


17
Perché evitare la ricorsione?
JorenB,


4
Non puoi fare nulla con tutti gli elementi di una matrice arbitrariamente profonda senza ricorsione (puoi mascherarlo come iterazione, ma patata, potahto.) Se vuoi solo evitare di scrivere tu stesso il codice di gestione della ricorsione, usa dk2.php.net/ manual / it / function.array-walk-recursive.php con un callback che aggiunge l'elemento a un array disponibile (usa global, il parametro userdata, metti tutto in una classe e fai riferimento a $ this, ecc.)
Michael Madsen

@JorenB: Mi piacerebbe vedere che un'implementazione potesse essere archiviata.
Alix Axel,

Dai un'occhiata alla funzione appiattisci di Nspl . Puoi anche specificare una profondità con esso.
Ihor Burlachenko,

Risposte:


276

È possibile utilizzare la libreria PHP standard (SPL) per "nascondere" la ricorsione.

$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($a));
foreach($it as $v) {
  echo $v, " ";
}

stampe

1 2 3 4 5 6 7 8 9 

351
Sono l'unico che pensa che "RecursiveIteratorIterator" sia un nome sciocco?
nilamo,

45
È più "logico" che "accattivante". Non tutto può avere un nome fantastico come JOGL, Knol o Azure :-)
VolkerK

7
Questo non funzionerà con array vuoti da bambini. Saranno restituiti come genitore.
Hacre,

45
iterator_to_array($it, false)evita la necessità del foreach.
Alix Axel,

3
Basandomi su ciò che gli altri hanno presentato, sono stato in grado di creare questo piccolo aiutante: function flatten($arr){ $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr)); return iterator_to_array($it, true); }spero che questo aiuti gli altri.
Mike S.

296

A partire da PHP 5.3 la soluzione più breve sembra essere array_walk_recursive()con la nuova sintassi delle chiusure:

function flatten(array $array) {
    $return = array();
    array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
    return $return;
}

33
se vuoi i tasti, funzione flatten (array $ array) {$ return = array (); array_walk_recursive ($ array, funzione ($ a, $ b) use (& $ return) {$ return [$ b] = $ a;}); return $ return; }
Brendon-Van-Heyzen il

puoi riscriverlo per usarlo con php 5.2?
Alex

2
@Alex sfortunatamente hai bisogno della usesintassi per farlo funzionare array_walk_recursivepoiché non accetterà il $userdataparametro opzionale per riferimento
Tim Seguine

1
Sembra funzionare bene per tali array -> ideone.com/DsmApP Ma non per tali array -> ideone.com/5Kltva O sono io?
Sebastian Piskorski,

2
@Sebastian Piskorski è perché i tuoi valori vengono trattati come chiavi, quindi non appena introduci la tua chiave => coppia di valori in un array, i tuoi valori di array nella prima posizione di indice vengono trattati come chiavi senza valori e poiché le chiavi hanno per essere univoci, in cui due chiavi corrispondono, i tuoi valori vengono aggiunti alla stessa chiave. Una soluzione semplice sarebbe quella di ordinare prima l'array. Questo è un comportamento inerente a PHP.
Martyn Shutt,

92

Soluzione per array bidimensionali

Per favore prova questo:

$array  = your array

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

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

EDIT: 21-ago-13

Ecco la soluzione che funziona per array multidimensionali:

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

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


Grazie, il primo ha funzionato su un array che stavo ottenendo dal DOP, dove le altre soluzioni no.
JAL

7
Questa è una strategia scadente. call_user_func_array('array_merge', [])(nota l'array vuoto) restituisce null e attiva un errore di avviso php. È una soluzione semplice se sai per certo che il tuo array non sarà vuoto, ma questo non è un presupposto comune che molti possono fare.
capra il

L'OP ha chiesto specificamente soluzioni non ricorsive.
Élektra,

Wow, cool 2d flattern! Ma per evitare preavviso basta usare$result = $array ?call_user_func_array('array_merge', $array) : [];
Alexander Goncharov

bello bruh, ma non hai per caso un array-deflatten contro-funzione?
FantomX1,

64

In PHP 5.6 e versioni successive è possibile appiattire gli array bidimensionali array_mergedopo aver decompresso l'array esterno con l' ...operatore. Il codice è semplice e chiaro.

array_merge(...$a);

Funziona anche con la raccolta di array associativi.

$a = [[10, 20], [30, 40]];
$b = [["x" => "X", "y" => "Y"], ["p" => "P", "q" => "Q"]];

print_r(array_merge(...$a));
print_r(array_merge(...$b));

Array
(
    [0] => 10
    [1] => 20
    [2] => 30
    [3] => 40
)
Array
(
    [x] => X
    [y] => Y
    [p] => P
    [q] => Q
)

Ma non funziona quando l'array esterno ha tasti non numerici. In tal caso, dovrai array_valuesprima chiamare .

$c = ["a" => ["x" => "X", "y" => "Y"], "b" => ["p" => "P", "q" => "Q"]];
print_r(array_merge(...array_values($c)));

Array
(
    [x] => X
    [y] => Y
    [p] => P
    [q] => Q
)

Aggiornamento: basato sul commento di @MohamedGharib

Questo genererà un errore se l'array esterno è vuoto, poiché array_mergeverrebbe chiamato con zero argomenti. Può essere evitato aggiungendo un array vuoto come primo argomento.

array_merge([], ...$a);

1
Funziona SOLO quando ogni elemento dell'array è un array. Se l'array comprende tipi misti, ad esempio scalari, si verificherà un errore.
Otheus,

@Otheus Questo perché la soluzione di cui sopra non utilizza la ricorsione. Come hai detto, richiede una matrice di array. Tra i lati positivi, questo dovrebbe essere molto più veloce rispetto agli altri metodi, poiché non ha l'overhead aggiuntivo delle chiamate di funzione.
Joyce Babu,

2
Emetterà un errore se l'array esterno è vuoto, potrebbe essere evitabile se combinato con un array vuotoarray_merge([], ...$a);
Mohamed Gharib

@MohamedGharib Nice catch.
Joyce Babu

Se si utilizzano array associativi è possibile controllare questa soluzione stackoverflow.com/questions/40663687/…
alex

24

Per appiattire senza ricorsione (come richiesto), è possibile utilizzare uno stack . Naturalmente puoi metterlo in una funzione a sé stante array_flatten. La seguente è una versione che funziona senza chiavi :.

function array_flatten(array $array)
{
    $flat = array(); // initialize return array
    $stack = array_values($array); // initialize stack
    while($stack) // process stack until done
    {
        $value = array_shift($stack);
        if (is_array($value)) // a value to further process
        {
            $stack = array_merge(array_values($value), $stack);
        }
        else // a value to take
        {
           $flat[] = $value;
        }
    }
    return $flat;
}

Gli elementi vengono elaborati nel loro ordine. Poiché i sottoelementi verranno spostati in cima allo stack, verranno successivamente elaborati.

È possibile prendere in considerazione anche le chiavi, tuttavia è necessaria una strategia diversa per gestire lo stack. Ciò è necessario perché è necessario gestire eventuali chiavi duplicate negli array secondari. Una risposta simile in una domanda correlata: PHP Cammina attraverso un array multidimensionale preservando le chiavi

Non ne sono particolarmente sicuro, ma in passato l'avevo provato: RecurisiveIteratorusa la ricorsione, quindi dipende da ciò di cui hai veramente bisogno. Dovrebbe essere possibile creare un iteratore ricorsivo basato anche su stack:

foreach(new FlatRecursiveArrayIterator($array) as $key => $value)
{
    echo "** ($key) $value\n";
}

dimostrazione

Non ci sono riuscito finora, per implementare lo stack in base al RecursiveIteratorquale penso sia una buona idea.


+1 per la straordinaria funzione array_flatten. Ho dovuto aggiungere if(!empty($value)){$flat[] = $value}all'interno dell'istruzione else per impedire l'aggiunta vuota alla matrice dei risultati. Funzione fantastica!
Alex Sarnowski,

19

Semplice e One-liner risposta.

function flatten_array(array $array)
{
    return iterator_to_array(
         new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array)));
}

Uso:

$array = [
    'name' => 'Allen Linatoc',
    'profile' => [
        'age' => 21,
        'favourite_games' => [ 'Call of Duty', 'Titanfall', 'Far Cry' ]
    ]
];

print_r( flatten_array($array) );

Uscita (in PsySH):

Array
(
    [name] => Allen Linatoc
    [age] => 21
    [0] => Call of Duty
    [1] => Titanfall
    [2] => Far Cry
)

Ora dipende da te ora come gestirai le chiavi. Saluti


EDIT (2017-03-01)

Citando la preoccupazione / problema di Nigel Alderton :

Solo per chiarire, questo conserva le chiavi (anche quelle numeriche) in modo che i valori che hanno la stessa chiave vadano persi. Ad esempio $array = ['a',['b','c']]diventa Array ([0] => b, [1] => c ). Si 'a'è perso perché 'b'ha anche una chiave di0

Citando la risposta di Svish :

Aggiungi false come secondo parametro ($use_keys)alla chiamata iterator_to_array


Solo per chiarire, questo conserva le chiavi (anche quelle numeriche) in modo che i valori che hanno la stessa chiave vadano persi. Ad esempio $array = ['a',['b','c']]diventa Array ([0] => b, [1] => c ). Si 'a'è perso perché 'b'ha anche una chiave di 0.
Nigel Alderton,

1
@NigelAlderton Basta aggiungere falsecome secondo parametro ( $use_keys) alla iterator_to_arraychiamata.
Svish,

18

Usa la ricorsione. Speriamo di vedere quanto non sia complesso, la tua paura della ricorsione si dissiperà quando vedrai quanto non è complesso.

function flatten($array) {
    if (!is_array($array)) {
        // nothing to do if it's not an array
        return array($array);
    }

    $result = array();
    foreach ($array as $value) {
        // explode the sub-array, and add the parts
        $result = array_merge($result, flatten($value));
    }

    return $result;
}


$arr = array('foo', array('nobody', 'expects', array('another', 'level'), 'the', 'Spanish', 'Inquisition'), 'bar');
echo '<ul>';
foreach (flatten($arr) as $value) {
    echo '<li>', $value, '</li>';
}
echo '<ul>';

Produzione:

<ul><li>foo</li><li>nobody</li><li>expects</li><li>another</li><li>level</li><li>the</li><li>Spanish</li><li>Inquisition</li><li>bar</li><ul>

1
Non temo la ricorsione, voglio solo imparare altri modi per fare lo stesso.
Alix Axel,

13
+1 per questa ricorsione: Spero che, vedendo quanto non sia complessa, la tua paura della ricorsione si dissipi quando vedrai quanto non è complessa.
Tiberiu-Ionuț Stan,

1
OK, questo è su di me. Com'è possibile, che la risposta ("Non temo la ricorsione") ha tre anni e mezzo in più (24 agosto 2009) rispetto alla dichiarazione iniziale ("(...) la tua paura della ricorsione si dissiperà (... ) "), realizzato il 5 febbraio 13?
trejder,

18

Ho pensato di sottolineare che questa è una piega, quindi array_reduce può essere usato:

array_reduce($my_array, 'array_merge', array());

EDIT: Nota che questo può essere composto per appiattire qualsiasi numero di livelli. Possiamo farlo in diversi modi:

// Reduces one level
$concat   = function($x) { return array_reduce($x, 'array_merge', array()); };

// We can compose $concat with itself $n times, then apply it to $x
// This can overflow the stack for large $n
$compose  = function($f, $g) {
    return function($x) use ($f, $g) { return $f($g($x)); };
};
$identity = function($x) { return $x; };
$flattenA = function($n) use ($compose, $identity, $concat) {
    return  function($x) use ($compose, $identity, $concat, $n) {
        return ($n === 0)? $x
                         : call_user_func(array_reduce(array_fill(0, $n, $concat),
                                                       $compose,
                                                       $identity),
                                          $x);
    };
};

// We can iteratively apply $concat to $x, $n times
$uncurriedFlip     = function($f) {
    return  function($a, $b) use ($f) {
        return $f($b, $a);
    };
};
$iterate  = function($f) use ($uncurriedFlip) {
    return  function($n) use ($uncurriedFlip, $f) {
    return  function($x) use ($uncurriedFlip, $f, $n) {
        return ($n === 0)? $x
                         : array_reduce(array_fill(0, $n, $f),
                                        $uncurriedFlip('call_user_func'),
                                        $x);
    }; };
};
$flattenB = $iterate($concat);

// Example usage:
$apply    = function($f, $x) {
    return $f($x);
};
$curriedFlip = function($f) {
    return  function($a) use ($f) {
    return  function($b) use ($f, $a) {
        return $f($b, $a);
    }; };
};

var_dump(
    array_map(
        call_user_func($curriedFlip($apply),
                       array(array(array('A', 'B', 'C'),
                                   array('D')),
                             array(array(),
                                   array('E')))),
        array($flattenA(2), $flattenB(2))));

Ovviamente, potremmo anche usare i loop ma la domanda richiede una funzione combinatrice lungo le linee di array_map o array_values.


Multidimensionale! = Bidimensionale.
Alix Axel,

@atamur Funziona su PHP 5.3+. Come notato nel log delle modifiche di array_reduce, $ initial potrebbe essere solo un numero intero prima della 5.3, quindi è stato permesso di essere "misto" (cioè qualsiasi cosa la tua funzione di riduzione supporti)
Warbo

1
@AlixAxel Hai ragione che multidimensionale! = Bidimensionale, ma questo può essere composto per appiattire un numero qualsiasi di livelli. Una bella conseguenza della composizione delle pieghe è che obbedisce a un limite fisso; se ho un array nidificato su 5 livelli, posso foldfarlo su 4 livelli, oppure fold . foldper ottenere 3 livelli, oppure fold . fold . foldper ottenere 2 livelli, ecc. Ciò impedisce anche che i bug vengano nascosti; per esempio. se voglio appiattire un array 5D ma mi viene dato un array 4D, l'errore si innescherà immediatamente.
Warbo,

Adoro questa soluzione, per array bidimensionali. Si adatta perfettamente al conto.
Tom Auger,

Sono d'accordo che la tua definizione a livello singolo sia la risposta migliore, è anche meravigliosamente pulita. Comunque penso che tu l'abbia erroneamente chiamato $concat, penso che dovresti semplicemente chiamarlo $flatten. array_mergeè l'equivalente php di concat. Ho provato ad essere array_concataggiunto come alias per array_merge.
icc97,

9

Appiattisce solo array bidimensionali:

$arr = [1, 2, [3, 4]];
$arr = array_reduce($arr, function ($a, $b) {
     return array_merge($a, (array) $b);
}, []);

// Result: [1, 2, 3, 4]

5

Questa soluzione non è ricorsiva. Si noti che l'ordine degli elementi sarà alquanto misto.

function flatten($array) {
    $return = array();
    while(count($array)) {
        $value = array_shift($array);
        if(is_array($value))
            foreach($value as $sub)
                $array[] = $sub;
        else
            $return[] = $value;
    }
    return $return;
}

1
Un'idea intelligente, ma c'è un bug. "$ array [] = $ value" non aggiunge tutti gli elementi di $ value a $ array, ma semplicemente aggiunge $ value stesso. Se si esegue questo codice, verrà eseguito un ciclo indefinito.
Todd Owen,

Sì, shiftingil valore fuori dall'array e aggiungendolo nuovamente alla fine non ha molto senso. Immagino che tu volessi array_merge()invece?
Inganno

4

Credo che questa sia la soluzione più pulita senza usare mutazioni o classi sconosciute.

<?php

function flatten($array)
{
    return array_reduce($array, function($acc, $item){
        return array_merge($acc, is_array($item) ? flatten($item) : [$item]);
    }, []);
}


// usage
$array = [1, 2, [3, 4], [5, [6, 7]], 8, 9, 10];
print_r(flatten($array));

3

Prova la seguente semplice funzione:

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

Quindi da questo:

array (
  'und' => 
  array (
    'profiles' => 
    array (
      0 => 
      array (
        'commerce_customer_address' => 
        array (
          'und' => 
          array (
            0 => 
            array (
              'first_name' => 'First name',
              'last_name' => 'Last name',
              'thoroughfare' => 'Address 1',
              'premise' => 'Address 2',
              'locality' => 'Town/City',
              'administrative_area' => 'County',
              'postal_code' => 'Postcode',
            ),
          ),
        ),
      ),
    ),
  ),
)

ottieni:

array (
  'first_name' => 'First name',
  'last_name' => 'Last name',
  'thoroughfare' => 'Address 1',
  'premise' => 'Address 2',
  'locality' => 'Town/City',
  'administrative_area' => 'County',
  'postal_code' => 'Postcode',
)

forse dovresti controllare la tua funzione ... sembra che non ci sia lavoro come previsto
Emiliano

@Emiliano Prova a fare una nuova domanda, forse i tuoi dati di input sono diversi, quindi non funzioneranno nel tuo caso particolare.
Kenorb,

abbiamo pochi problemi ognuno è una funzione deprecata, puoi migliorare quel punto in cui non eri un ragazzo nuovo, dovresti saperlo in secondo luogo se il tuo codice funziona con una versione specifica di php dillo terzo se non funziona con tutti i dati dillo
Emiliano

2

Il trucco sta passando entrambi gli array di origine e di destinazione per riferimento.

function flatten_array(&$arr, &$dst) {
    if(!isset($dst) || !is_array($dst)) {
        $dst = array();
    }
    if(!is_array($arr)) {
        $dst[] = $arr;
    } else {
        foreach($arr as &$subject) {
            flatten_array($subject, $dst);
        }
    }
}

$recursive = array('1', array('2','3',array('4',array('5','6')),'7',array(array(array('8'),'9'),'10')));
echo "Recursive: \r\n";
print_r($recursive);
$flat = null;
flatten_array($recursive, $flat);

echo "Flat: \r\n";
print_r($flat);

// If you change line 3 to $dst[] = &$arr; , you won't waste memory,
// since all you're doing is copying references, and imploding the array 
// into a string will be both memory efficient and fast:)

echo "String:\r\n";
echo implode(',',$flat);

2
/**
 * For merging values of a multidimensional array into one 
 *
 * $array = [
 *     0 => [
 *         0 => 'a1',
 *         1 => 'b1',
 *         2 => 'c1',
 *         3 => 'd1'
 *     ],
 *     1 => [
 *         0 => 'a2',
 *         1 => 'b2',
 *         2 => 'c2',
 *     ]
 * ];
 *
 * becomes : 
 *
 * $array = [
 *     0 => 'a1',
 *     1 => 'b1',
 *     2 => 'c1',
 *     3 => 'd1',
 *     4 => 'a2',
 *     5 => 'b2',
 *     6 => 'c2',
 *     
 * ]
 */
array_reduce
(
    $multiArray
    , function ($lastItem, $currentItem) {
        $lastItem = $lastItem ?: array();
        return array_merge($lastItem, array_values($currentItem));
    }
);

Snippet Gist


Questo sembra supportare solo array bidimensionali.
Alix Axel,

Hai ragione. Non ha senso usarlo. Penso che la soluzione migliore sia la risposta di "troppo php".
Arsham,


2

Se davvero non ti piace una ricorsione ... prova invece a cambiare :)

$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
$o = [];
for ($i=0; $i<count($a); $i++) {
    if (is_array($a[$i])) {
        array_splice($a, $i+1, 0, $a[$i]);
    } else {
        $o[] = $a[$i];
    }
}

Nota: in questa versione semplice, questo non supporta le chiavi dell'array.


questo è un approccio interessante. in contrasto con le altre soluzioni, modifica l'array originale ($ a). Se lo sostituisci con a continue, è un po 'più veloce.
pcarvalho,

2

Che ne dici di usare un generatore ricorsivo? https://ideone.com/d0TXCg

<?php

$array = [
    'name' => 'Allen Linatoc',
    'profile' => [
        'age' => 21,
        'favourite_games' => [ 'Call of Duty', 'Titanfall', 'Far Cry' ]
    ]
];

foreach (iterate($array) as $item) {
    var_dump($item);
};

function iterate($array)
{
    foreach ($array as $item) {
        if (is_array($item)) {
            yield from iterate($item);
        } else {
            yield $item;
        }
    }
}

1

Per php 5.2

function flatten(array $array) {
    $result = array();

    if (is_array($array)) {
        foreach ($array as $k => $v) {
            if (is_array($v)) {
                $result = array_merge($result, flatten($v));
            } else {
                $result[] = $v;
            }
        }
    }

    return $result;
}

Si prega di includere alcune spiegazioni con questa risposta di solo codice.
Mickmackusa,

1

Questa versione può eseguire livelli profondi, superficiali o specifici:

/**
 * @param  array|object $array  array of mixed values to flatten
 * @param  int|boolean  $level  0:deep, 1:shallow, 2:2 levels, 3...
 * @return array
 */
function flatten($array, $level = 0) {
    $level = (int) $level;
    $result = array();
    foreach ($array as $i => $v) {
        if (0 <= $level && is_array($v)) {
            $v = flatten($v, $level > 1 ? $level - 1 : 0 - $level);
            $result = array_merge($result, $v);
        } elseif (is_int($i)) {
            $result[] = $v;
        } else {
            $result[$i] = $v; 
        }
    }
    return $result;
}

Oltre a spiegare cosa può fare questo frammento , spiega ai futuri ricercatori come funziona.
Mickmackusa,

1

Perché il codice qui sembra spaventoso. Ecco una funzione che converte anche un array multidimensionale in sintassi compatibile con html, ma che è più facile da leggere.

/**
 * Flattens a multi demensional array into a one dimensional
 * to be compatible with hidden html fields.
 *
 * @param array $array
 *  Array in the form:
 *  array(
 *    'a' => array(
 *      'b' => '1'
 *    )
 *  )
 *
 * @return array
 *  Array in the form:
 *  array(
 *    'a[b]' => 1,
 *  )
 */
function flatten_array($array) {
  // Continue until $array is a one-dimensional array.
  $continue = TRUE;
  while ($continue) {
    $continue = FALSE;

    // Walk through top and second level of $array and move 
    // all values in the second level up one level.
    foreach ($array as $key => $value) {
      if (is_array($value)) {
        // Second level found, therefore continue.
        $continue = TRUE;

        // Move each value a level up.
        foreach ($value as $child_key => $child_value) {
          $array[$key . '[' . $child_key . ']'] = $child_value;
        }

        // Remove second level array from top level.
        unset($array[$key]);
      }
    }
  }

  return $array;
}

1

Questo può essere ottenuto utilizzando array_walk_recursive

$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
array_walk_recursive($a, function($v) use (&$r){$r[]=$v;});
print_r($r);

Esempio di lavoro: - https://3v4l.org/FpIrG


0

Questa è la mia soluzione, usando un riferimento:

function arrayFlatten($array_in, &$array_out){

    if(is_array($array_in)){
        foreach ($array_in as $element){
               arrayFlatten($element, $array_out);
        }
    }
    else{
        $array_out[] = $array_in; 
    }
}

$arr1 = array('1', '2', array(array(array('3'), '4', '5')), array(array('6')));

arrayFlatten($arr1, $arr2);

echo "<pre>";
print_r($arr2);
echo "</pre>";

Includi alcune spiegazioni su come funziona il tuo snippet e perché è una buona idea. Le risposte di solo codice sono di scarso valore su StackOverflow perché svolgono un cattivo lavoro di educazione / potenziamento del PO e dei futuri ricercatori. Ricorda, non stiamo mai parlando SOLO all'OP; le vecchie pagine vengono utilizzate per chiudere nuove pagine, quindi le pagine devono essere sufficientemente informative per risolvere i problemi anche per i futuri richiedenti.
Mickmackusa,

0
<?php
//recursive solution

//test array
$nested_array = [[1,2,[3]],4,[5],[[[6,[7=>[7,8,9,10]]]]]];

/*-----------------------------------------
function call and return result to an array
------------------------------------------*/
$index_count = 1;
$flatered_array = array();
$flatered_array = flat_array($nested_array, $index_count);

/*-----------------------------------------
Print Result
-----------------------------------------*/
echo "<pre>";
print_r($flatered_array);


/*-----------------------------------------
function to flaten an array 
-----------------------------------------*/
function flat_array($nested_array, & $index_count, & $flatered_array) {

  foreach($nested_array AS $key=>$val) {
      if(is_array($val)) {
        flat_array($val, $index_count, $flatered_array);
      }
      else {
        $flatered_array[$index_count] = $val;
        ++$index_count;
      }      
  }

return $flatered_array;
}
?>

0

Ecco un approccio semplicistico:

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

function checkArray($value) {
    foreach ($value as $var) {
        if ( is_array($var) ) {
            checkArray($var);
        } else {
            echo $var;
        }
    }
}

checkArray($My_Array);

0

Chiunque cerchi una soluzione davvero pulita a questo; ecco un'opzione:

$test_array = array(
    array('test' => 0, 0, 0, 0),
    array(0, 0, 'merp' => array('herp' => 'derp'), 0),
    array(0, 0, 0, 0),
    array(0, 0, 0, 0)
);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($test_array));
var_dump( iterator_to_array($it, false) ) ; 

stampe

 0 0 0 0 0 0 derp 0 0 0 0 0 0 0 0 0

0

Pubblicando solo un'altra soluzione)

function flatMultidimensionalArray(array &$_arr): array
{
    $result = [];
    \array_walk_recursive($_arr, static function (&$value, &$key) use (&$result) {
        $result[$key] = $value;
    });

    return $result;
}

0

Se vuoi conservare anche le tue chiavi, questa è la soluzione.

function reduce(array $array) {
    $return = array();
    array_walk_recursive($array, function($value, $key) use (&$return) { $return[$key] = $value; });
    return $return;
}

Sfortunatamente genera solo array nidificati finali, senza tasti centrali. Quindi, per il seguente esempio:

$array = array(
    'sweet' => array(
        'a' => 'apple',
        'b' => 'banana'),
    'sour' => 'lemon'); 
print_r(flatten($fruits));

L'output è:

Array
(
    [a] => apple
    [b] => banana
    [sour] => lemon
)

-1

Avevo bisogno di rappresentare l'array multidimensionale PHP in formato di input HTML.

$test = [
    'a' => [
        'b' => [
            'c' => ['a', 'b']
        ]
    ],
    'b' => 'c',
    'c' => [
        'd' => 'e'
    ]
];

$flatten = function ($input, $parent = []) use (&$flatten) {
    $return = [];

    foreach ($input as $k => $v) {
        if (is_array($v)) {
            $return = array_merge($return, $flatten($v, array_merge($parent, [$k])));
        } else {
            if ($parent) {
                $key = implode('][', $parent) . '][' . $k . ']';

                if (substr_count($key, ']') != substr_count($key, '[')) {
                    $key = preg_replace('/\]/', '', $key, 1);
                }
            } else {
                $key = $k;
            }           

            $return[$key] = $v;
        }
    }

    return $return;
};

die(var_dump( $flatten($test) ));

array(4) {
  ["a[b][c][0]"]=>
  string(1) "a"
  ["a[b][c][1]"]=>
  string(1) "b"
  ["b"]=>
  string(1) "c"
  ["c[d]"]=>
  string(1) "e"
}


@AlixAxel Come è relativo questo commento? Post sbagliato ..?
Gajus,

No. Ho pensato che fosse abbastanza simile a quello che stai facendo e ho deciso di condividerlo, penso che l'unica differenza sia che la mia rappresentazione è anche PHP valida - del modulo $var['a']['b']['c'][0] = 'a'; ....
Alix Axel,

Avevo bisogno intenzionalmente di output HTML. Sebbene grazie per averlo condiviso.
Gajus,

1
Sento che questa è la risposta giusta alla domanda sbagliata. Quando rispondi, prova a rispondere alla domanda quando viene posta, altrimenti le pagine potrebbero discostarsi dal problema principale e lasciare confusi i futuri ricercatori.
Mickmackusa,

-1

Se si dispone di una matrice di oggetti e si desidera appiattirla con un nodo, utilizzare questa funzione:

function objectArray_flatten($array,$childField) {
    $result = array();
    foreach ($array as $node)
    {
        $result[] = $node;
        if(isset($node->$childField))
        {
            $result = array_merge(
                $result, 
                objectArray_flatten($node->$childField,$childField)
            );
            unset($node->$childField);
        }

    }
    return $result;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.