¿Cómo aplanar una matriz multidimensional?

259

¿Es posible, en PHP, aplanar una matriz (bi / multi) dimensional sin usar recursividad o referencias?

Solo me interesan los valores para que las claves puedan ignorarse, estoy pensando en las líneas de array_map()y array_values().

Alix Axel
fuente
17
¿Por qué evitar la recursividad?
JorenB
55
Dupe (en su mayoría) stackoverflow.com/questions/526556/…
cletus
44
No puede hacer nada con todos los elementos de una matriz arbitrariamente profunda sin recursión (puede disfrazarlo como iteración, pero papa, potahto). Si solo desea evitar escribir el código de manejo de recursión usted mismo, use dk2.php.net/ manual / es / function.array-walk-recursive.php con una devolución de llamada que agrega el elemento a una matriz disponible (use global, el parámetro userdata, colóquelo todo en una clase y consulte $ this, etc.)
Michael Madsen
@JorenB: Me gustaría ver que se pueda archivar una implementación.
Alix Axel el
Echa un vistazo a la función de aplanar de Nspl . También puede especificar una profundidad con él.
Ihor Burlachenko

Respuestas:

276

Puede usar la Biblioteca PHP estándar (SPL) para "ocultar" la recursividad.

$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, " ";
}

huellas dactilares

1 2 3 4 5 6 7 8 9 
VolkerK
fuente
351
¿Soy el único que piensa que 'RecursiveIteratorIterator' es un nombre tonto?
nilamo
45
Es más "lógico" que "pegadizo". No todo puede tener un nombre fantástico como JOGL, Knol o Azure :-)
VolkerK
77
Esto no funcionará para matrices vacías como elementos secundarios. Serán devueltos como padres.
Hakre
45
iterator_to_array($it, false)evita la necesidad del foreach.
Alix Axel
3
Sobre la base de lo que otros presentaron, pude crear este pequeño ayudante: function flatten($arr){ $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr)); return iterator_to_array($it, true); }espero que esto ayude a otros.
Mike S.
296

A partir de PHP 5.3, la solución más corta parece ser array_walk_recursive()con la nueva sintaxis de cierres:

function flatten(array $array) {
    $return = array();
    array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
    return $return;
}
demasiado php
fuente
33
si quiere teclas, la función flatten (array $ array) {$ return = array (); array_walk_recursive ($ array, function ($ a, $ b) use (& $ return) {$ return [$ b] = $ a;}); return $ return; }
Brendon-Van-Heyzen
¿puedes reescribir esto para usar con php 5.2?
Alex
2
@Alex, desafortunadamente, necesita la usesintaxis para que funcione, array_walk_recursiveya que no aceptará el $userdataparámetro opcional por referencia
Tim Seguine
1
Parece que funciona bien para tales matrices -> ideone.com/DsmApP Pero no para tales -> ideone.com/5Kltva ¿ O soy yo?
Sebastian Piskorski
2
@Sebastian Piskorski es porque sus valores se tratan como claves, por lo que tan pronto como introduzca su propio par clave => valor en una matriz, sus valores de matriz en la primera posición del índice se tratan como claves sin valores, y porque las claves tienen para ser único, donde coinciden dos claves, sus valores se agregan a la misma clave. Una solución simple sería ordenar primero la matriz. Este es un comportamiento inherente a PHP.
Martyn Shutt
92

Solución para arreglo bidimensional

Por favor intente esto:

$array  = your array

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

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

EDITAR: 21-ago-13

Aquí está la solución que funciona para una matriz multidimensional:

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

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

Prasanth Bendra
fuente
Gracias, el primero funcionó en una matriz que estaba obteniendo de PDO donde las otras soluciones no.
JAL
77
Esta es una mala estrategia. call_user_func_array('array_merge', [])(observe la matriz vacía) devuelve nulo y desencadena un error de advertencia de php. Es una solución ingeniosa si sabe con certeza que su matriz no estará vacía, pero esa no es una suposición común que muchos pueden hacer.
cabra
El OP solicitó específicamente soluciones no recursivas.
Élektra
Wow, genial 2d flattern! Pero para evitar avisos solo use$result = $array ?call_user_func_array('array_merge', $array) : [];
Alexander Goncharov
genial, pero ¿no tienes por casualidad un deflactor de matriz de contrafunción?
FantomX1
64

En PHP 5.6 y superior, puede aplanar matrices bidimensionales array_mergedespués de desempaquetar la matriz externa con el ...operador. El código es simple y claro.

array_merge(...$a);

Esto también funciona con la colección de matrices asociativas.

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

Pero no funciona cuando la matriz externa tiene claves no numéricas. En ese caso, array_valuesprimero deberá llamar .

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

Actualización: Basado en el comentario de @MohamedGharib

Esto arrojará un error si la matriz externa está vacía, ya array_mergeque se llamaría con cero argumentos. Se puede evitar agregando una matriz vacía como primer argumento.

array_merge([], ...$a);
Joyce Babu
fuente
1
Esto funciona SOLO cuando cada elemento de la matriz es una matriz. Si la matriz comprende tipos mixtos, como escalares, se producirá un error.
Oteo
@Otheus Eso se debe a que la solución anterior no utiliza la recursividad. Como dijiste, requiere una matriz de matriz. Pero en el lado positivo, esto debería ser mucho más rápido que los otros métodos, ya que no tiene la sobrecarga adicional de las llamadas a funciones.
Joyce Babu el
2
Lanzará un error si la matriz externa está vacía, podría evitarse si se combina con una matriz vacíaarray_merge([], ...$a);
Mohamed Gharib
@MohamedGharib Buena captura.
Joyce Babu
Si usa matrices asociativas, puede consultar esta solución stackoverflow.com/questions/40663687/…
alex
24

Para aplanar sin recursión (como ha pedido), puede usar una pila . Naturalmente, puede poner esto en una función propia array_flatten. La siguiente es una versión que funciona sin teclas :.

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

Los elementos se procesan en su orden. Como los subelementos se moverán sobre la pila, se procesarán a continuación.

También es posible tener en cuenta las claves, sin embargo, necesitará una estrategia diferente para manejar la pila. Eso es necesario porque necesita lidiar con posibles claves duplicadas en los sub-arrays. Una respuesta similar en una pregunta relacionada: PHP Recorre la matriz multidimensional mientras conserva las claves

No estoy específicamente seguro, pero lo he probado en el pasado: RecurisiveIteratorutiliza la recursividad, por lo que depende de lo que realmente necesita. También debería ser posible crear un iterador recursivo basado en pilas:

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

Manifestación

No llegué hasta ahora, para implementar la pila en base a la RecursiveIteratorcual creo que es una buena idea.

hakre
fuente
+1 para la destacada función array_flatten. Tuve que agregar if(!empty($value)){$flat[] = $value}dentro de la instrucción else para evitar que se agregue vacío a la matriz de resultados. Función impresionante!
Alex Sarnowski el
19

Respuesta directa y de una sola línea .

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

Salida (en PsySH):

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

Ahora depende de ti cómo manejarás las llaves. Salud


EDITAR (2017-03-01)

Citando la preocupación / problema de Nigel Alderton :

Solo para aclarar, esto conserva las claves (incluso las numéricas) para que los valores que tienen la misma clave se pierdan. Por ejemplo se $array = ['a',['b','c']]convierte Array ([0] => b, [1] => c ). El 'a'se pierde porque 'b'también tiene una clave de0

Citando la respuesta de Svish :

Simplemente agregue falso como segundo parámetro ($use_keys)a la llamada iterator_to_array

Allen Linatoc
fuente
Solo para aclarar, esto conserva las claves (incluso las numéricas) para que los valores que tienen la misma clave se pierdan. Por ejemplo se $array = ['a',['b','c']]convierte Array ([0] => b, [1] => c ). El 'a'se pierde porque 'b'también tiene una clave de 0.
Nigel Alderton
1
@NigelAlderton Simplemente agregue falsecomo segundo parámetro ( $use_keys) a la iterator_to_arrayllamada.
Svish
18

Utiliza la recursividad. Con suerte, al ver lo poco complejo que es, su miedo a la recurrencia se disipará una vez que vea lo poco complejo que es.

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

Salida:

<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>
nilamo
fuente
1
No le temo a la recursión, solo quiero aprender otras formas de hacer lo mismo.
Alix Axel
13
+1 para esta recursividad: con suerte, al ver cuán no complejo es, su miedo a la recursión se disipará una vez que vea cuán no complejo es.
Tiberiu-Ionuț Stan
1
OK, esto se acabó. Cómo es posible, esa respuesta ("No temo la recurrencia") es tres años y medio mayor (24 de agosto de 2009) que la declaración inicial ("(...) su miedo a la recurrencia se disipará (... ) "), realizado el 5 de febrero de 2013?
trejder
18

Solo pensé en señalar que esto es un pliegue, por lo que se puede usar array_reduce:

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

EDITAR: Tenga en cuenta que esto se puede componer para aplanar cualquier número de niveles. Podemos hacer esto de varias maneras:

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

Por supuesto, también podríamos usar bucles, pero la pregunta pide una función de combinador a lo largo de las líneas de array_map o array_values.

Warbo
fuente
¡Multidimensional! = Bidimensional.
Alix Axel
@atamur Esto funciona en PHP 5.3+. Como se señaló en el registro de cambios para array_reduce, $ initial solo podía ser un número entero antes de 5.3, luego se le permitió "mezclar" (es decir, cualquier cosa que su función de reducción admita)
Warbo
1
@AlixAxel ¡Tienes razón en que es multidimensional! = Bidimensional, pero esto se puede componer para aplanar cualquier número de niveles. Una buena consecuencia de componer pliegues es que obedece a un límite fijo; si tengo una matriz anidada en 5 niveles, puedo foldcolocarla en 4 niveles, o fold . foldobtener 3 niveles, o fold . fold . foldobtener 2 niveles, etc. Esto también evita que los errores se oculten; p.ej. si quiero aplanar una matriz 5D pero me dan una matriz 4D, el error se activará de inmediato.
Warbo
Me encanta esta solución, para matrices bidimensionales. Se adapta perfectamente a la factura.
Tom Auger
Estoy de acuerdo en que su definición de nivel único es la mejor respuesta, también es maravillosamente ordenada. Sin embargo, creo que lo nombraste incorrectamente $concat, creo que deberías llamarlo $flatten. array_mergees el equivalente php de concat. Traté de ser array_concatagregado como un alias para array_merge.
icc97
9

Aplana solo matrices bidimensionales:

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

// Result: [1, 2, 3, 4]
artnikpro
fuente
5

Esta solución no es recursiva. Tenga en cuenta que el orden de los elementos será algo mixto.

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;
}
demasiado php
fuente
1
Idea inteligente, pero hay un error. "$ array [] = $ value" no agrega todos los elementos de $ value a $ array, simplemente agrega $ value en sí. Si ejecuta este código, se repetirá indefinidamente.
Todd Owen el
Sí, shiftingel valor de la matriz y agregarlo nuevamente al final no tiene mucho sentido. Supongo que querías hacerlo en su array_merge()lugar?
deceze
4

Creo que esta es la solución más limpia sin usar mutaciones ni clases desconocidas.

<?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));
Dariush Alipour
fuente
3

Pruebe la siguiente función simple:

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

Entonces de esto:

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

usted obtiene:

array (
  'first_name' => 'First name',
  'last_name' => 'Last name',
  'thoroughfare' => 'Address 1',
  'premise' => 'Address 2',
  'locality' => 'Town/City',
  'administrative_area' => 'County',
  'postal_code' => 'Postcode',
)
kenorb
fuente
quizás deberías revisar tu función ... parece que no funciona como se esperaba
Emiliano
@Emiliano Intente hacer una nueva pregunta, tal vez sus datos de entrada sean diferentes, por lo que no funcionarán en su caso particular.
kenorb
tenemos algunos problemas, cada uno es una función obsoleta, puede mejorar ese punto en el que no era un tipo nuevo aquí, debería saberlo en segundo lugar si su código funciona con una versión específica de php, dígalo en tercer lugar, si no funciona con todos los datos, dígalo
Emiliano
2

El truco es pasar las matrices de origen y de destino por referencia.

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);
Rick Garcia
fuente
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));
    }
);

Fragmento de Gist

Arsham
fuente
Esto parece solo admitir matrices bidimensionales.
Alix Axel
Tienes razón. No tiene sentido usarlo. Creo que la mejor solución es la respuesta de "demasiado php".
Arsham
2

Si realmente no te gusta una recursión ... prueba a cambiar :)

$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: en esta versión simple, esto no admite claves de matriz.

BurninLeo
fuente
Este es un enfoque interesante. en contraste con las otras soluciones, edita la matriz original ($ a). Si lo reemplaza con a continue, es algo más rápido.
pcarvalho
2

¿Qué tal usar un generador recursivo? 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;
        }
    }
}
Andriy
fuente
1

Para 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;
}
Alexei T
fuente
Incluya alguna explicación con esta respuesta de solo código.
mickmackusa
1

Esta versión puede hacer niveles profundos, superficiales o específicos:

/**
 * @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;
}
ryanve
fuente
Más allá de explicar qué puede hacer este fragmento , explique a los futuros investigadores cómo funciona.
mickmackusa
1

Porque el código aquí parece aterrador. Aquí hay una función que también convertirá una matriz multidimensional en una sintaxis compatible con formularios html, pero que es más fácil de leer.

/**
 * 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;
}
Gellweiler
fuente
1

Esto se puede lograr usando 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);

Ejemplo de trabajo: - https://3v4l.org/FpIrG

Rakesh Jakhar
fuente
0

Esta es mi solución, usando una referencia:

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>";
Martyn Shutt
fuente
Incluya alguna explicación de cómo funciona su fragmento y por qué es una buena idea. Las respuestas de solo código tienen poco valor en StackOverflow porque hacen un mal trabajo al educar / empoderar al OP y a los futuros investigadores. Recuerde, nunca estamos SOLAMENTE hablando con el OP; las páginas antiguas se utilizan para cerrar páginas nuevas, por lo que las páginas también deben ser lo suficientemente informativas como para resolver problemas para futuros usuarios.
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;
}
?>
Furqan liberado
fuente
0

Aquí hay un enfoque simplista:

$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);
Jack
fuente
0

Cualquiera que busque una solución realmente limpia para esto; Aquí hay una opción:

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

Huellas dactilares

 0 0 0 0 0 0 derp 0 0 0 0 0 0 0 0 0
Luis
fuente
0

Solo publicando una solución más)

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

    return $result;
}
James Bond
fuente
0

Si desea conservar también sus claves, esa es la solución.

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

Desafortunadamente, solo genera matrices anidadas finales, sin claves intermedias. Entonces para el siguiente ejemplo:

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

Salida es:

Array
(
    [a] => apple
    [b] => banana
    [sour] => lemon
)
Tajni
fuente
-1

Necesitaba representar la matriz multidimensional de PHP en formato de entrada 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"
}
Gajus
fuente
@AlixAxel ¿Cómo es relativo este comentario? Mensaje equivocado ..?
Gajus
No. Pensé que era bastante similar a lo que estás haciendo y decidí compartirlo, creo que la única diferencia es que mi representación también es PHP válido, de la forma $var['a']['b']['c'][0] = 'a'; ....
Alix Axel
Intencionalmente necesitaba salida HTML. Aunque gracias por compartir.
Gajus
1
Siento que esta es la respuesta correcta a la pregunta incorrecta. Al responder, intente responder la pregunta tal como se hace; de ​​lo contrario, las páginas pueden apartarse del tema central y confundir a los futuros investigadores.
mickmackusa
-1

Si tiene una matriz de objetos y desea aplanarla con un nodo, simplemente use esta función:

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;
}
حسین شکرزاده
fuente