valor unidimensional sumar multidimensional manejo functions eliminar elementos elemento convertir buscar array_flatten array agregar php arrays multidimensional-array flatten

php - unidimensional - ¿Cómo aplanar una matriz multidimensional?



php array functions (24)

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

¿Es posible, en PHP, aplanar un arreglo (bi / multi) dimensional sin usar recursión o referencias?

Solo me interesan los valores, por lo que las claves se pueden ignorar, estoy pensando en las líneas de array_map() y array_values() .


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]


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


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


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


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

$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, deberás llamar a array_values primero.

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


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


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

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


Esta versión puede ser profunda, superficial o un número específico de niveles:

/** * @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; }


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


Para aplanar sin recursión (como ha pedido), puede usar una stack . Naturalmente, puedes poner esto en una función propia como array_flatten . La siguiente es una versión que funciona con 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 subarreglos. Una respuesta similar en una pregunta relacionada: PHP Recorre una matriz multidimensional al tiempo que conserva las claves

No estoy específicamente seguro, pero yo había probado esto en el pasado: el RecurisiveIterator usa la recursión, por lo que depende de lo que realmente necesites. Debería ser posible crear un iterador recursivo basado en pilas también:

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

Demo

No llegué tan lejos, para implementar la pila basada en RecursiveIterator lo que creo que es una buena idea.


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


Porque el código here da miedo. Aquí hay una función que también convertirá una matriz multidimensional en una sintaxis compatible con el formato 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; }


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

Así que 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'', )


Puede usar la biblioteca estándar de PHP (SPL) para "ocultar" la recursión.

$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


Puedes hacerlo con golosinas ouzo :

$result = Arrays::flatten($multidimensional);

Ver: Here


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. Aclamaciones

EDITAR (2017-03-01)

Citando la preocupación / problema de Nigel Alderton :

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

Citando la respuesta de Svish :

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


Si realmente no te gusta una recursión ... intenta cambiar de lugar :)

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


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


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

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 combinadora a lo largo de las líneas de array_map o array_values.


Utiliza la recursividad. Con suerte, al ver cuán complejo no es, su miedo a la recursión se disipará una vez que vea cuán complejo no 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>


Solución para matriz 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


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


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