vacio multidimensional functions elementos ejemplos asociativo array agregar php arrays

functions - Transposición de matrices multidimensionales en PHP



php array functions (9)

Antes de comenzar, me gustaría dar las gracias nuevamente a @quazardus por publicar su solución generalizada para traspasar dos arreglos asociativos dimensionales (o no asociativos).

Como tengo la costumbre de escribir mi código de la forma más escueta posible, pasé a "minimizar" un poco más su código. Es muy probable que esto no sea ​​del gusto de todos. Pero por si acaso alguien debería estar interesado, aquí está mi opinión sobre su solución:

function arrayMap($cb, array $arrays) // $cb: optional callback function { $keys = []; array_walk($arrays, function ($array) use (&$keys) { $keys = array_merge($keys, array_keys($array)); }); $keys = array_unique($keys); $res = []; foreach ($keys as $key) { $items = array_map(function ($arr) use ($key) {return isset($arr[$key]) ? $arr[$key] : null; },$arrays); $res[$key] = call_user_func( is_callable($cb) ? $cb : function($k, $itms){return $itms;}, $key, $items); } return $res; }

Ahora, análoga a la función estándar PHP array_map() , cuando llamas

arrayMap(null,$b);

obtendrás la matriz transpuesta deseada.

¿Cómo cambiaría 90 grados (transponer) una matriz multidimensional en PHP? Por ejemplo:

// Start with this array $foo = array( ''a'' => array( 1 => ''a1'', 2 => ''a2'', 3 => ''a3'' ), ''b'' => array( 1 => ''b1'', 2 => ''b2'', 3 => ''b3'' ), ''c'' => array( 1 => ''c1'', 2 => ''c2'', 3 => ''c3'' ) ); $bar = flipDiagonally($foo); // Mystery function var_dump($bar[2]); // Desired output: array(3) { ["a"]=> string(2) "a2" ["b"]=> string(2) "b2" ["c"]=> string(2) "c2" }

¿Cómo implementaría flipDiagonally() ?

Editar: esto no es tarea. Solo quiero ver si alguna SO tiene una solución más creativa que la más obvia. Pero dado que unas pocas personas se han quejado de que este problema es demasiado fácil, ¿qué tal una solución más general que funcione con una matriz de dimensión n?

es decir, cómo escribirías una función para que:

$foo[j][k][...][x][y][z] = $bar[z][k][...][x][y][j]

? (ps. No creo que 12 for loops anidados for loops sea ​​la mejor solución en este caso).


Con 2 bucles

function flipDiagonally($arr) { $out = array(); foreach ($arr as $key => $subarr) { foreach ($subarr as $subkey => $subvalue) { $out[$subkey][$key] = $subvalue; } } return $out; }


Creo que te estás refiriendo a la matriz transpose (las columnas se convierten en filas, las filas se convierten en columnas).

Aquí hay una función que lo hace por usted (source) :

function array_transpose($array, $selectKey = false) { if (!is_array($array)) return false; $return = array(); foreach($array as $key => $value) { if (!is_array($value)) return $array; if ($selectKey) { if (isset($value[$selectKey])) $return[] = $value[$selectKey]; } else { foreach ($value as $key2 => $value2) { $return[$key2][$key] = $value2; } } } return $return; }


Me enfrenté con el mismo problema. Esto es lo que se me ocurrió:

function array_transpose(array $arr) { $keys = array_keys($arr); $sum = array_values(array_map(''count'', $arr)); $transposed = array(); for ($i = 0; $i < max($sum); $i ++) { $item = array(); foreach ($keys as $key) { $item[$key] = array_key_exists($i, $arr[$key]) ? $arr[$key][$i] : NULL; } $transposed[] = $item; } return $transposed; }


Necesitaba una función de transposición con soporte para matriz asociativa:

$matrix = [ [''one'' => 1, ''two'' => 2], [''one'' => 11, ''two'' => 22], [''one'' => 111, ''two'' => 222], ]; $result = /array_transpose($matrix); $trans = [ ''one'' => [1, 11, 111], ''two'' => [2, 22, 222], ];

Y el camino de regreso:

$matrix = [ ''one'' => [1, 11, 111], ''two'' => [2, 22, 222], ]; $result = /array_transpose($matrix); $trans = [ [''one'' => 1, ''two'' => 2], [''one'' => 11, ''two'' => 22], [''one'' => 111, ''two'' => 222], ];

El truco array_unshift no funcionó NOR el array_map ...

Así que he codificado una función array_map_join_array para tratar con la asociación de claves de registro:

/** * Similar to array_map() but tries to join values on intern keys. * @param callable $callback takes 2 args, the intern key and the list of associated values keyed by array (extern) keys. * @param array $arrays the list of arrays to map keyed by extern keys NB like call_user_func_array() * @return array */ function array_map_join_array(callable $callback, array $arrays) { $keys = []; // try to list all intern keys array_walk($arrays, function ($array) use (&$keys) { $keys = array_merge($keys, array_keys($array)); }); $keys = array_unique($keys); $res = []; // for each intern key foreach ($keys as $key) { $items = []; // walk through each array array_walk($arrays, function ($array, $arrKey) use ($key, &$items) { if (isset($array[$key])) { // stack/transpose existing value for intern key with the array (extern) key $items[$arrKey] = $array[$key]; } else { // or stack a null value with the array (extern) key $items[$arrKey] = null; } }); // call the callback with intern key and all the associated values keyed with array (extern) keys $res[$key] = call_user_func($callback, $key, $items); } return $res; }

y array_transpose hizo obvio:

function array_transpose(array $matrix) { return /array_map_join_array(function ($key, $items) { return $items; }, $matrix); }


Transposición de una matriz N-dimensional:

function transpose($array, &$out, $indices = array()) { if (is_array($array)) { foreach ($array as $key => $val) { //push onto the stack of indices $temp = $indices; $temp[] = $key; transpose($val, $out, $temp); } } else { //go through the stack in reverse - make the new array $ref = &$out; foreach (array_reverse($indices) as $idx) $ref = &$ref[$idx]; $ref = $array; } } $foo[1][2][3][3][3] = ''a''; $foo[4][5][6][5][5] = ''b''; $out = array(); transpose($foo, $out); echo $out[3][3][3][2][1] . '' '' . $out[5][5][6][5][4];

Realmente hackish, y probablemente no sea la mejor solución, pero bueno, funciona.

Básicamente atraviesa la matriz recursivamente, acumulando las indices actuales en una matriz.
Una vez que llega al valor referenciado, toma la "pila" de índices y la invierte, poniéndolo en la matriz $ out. (¿Hay alguna manera de evitar el uso de la matriz $ temp?)


Use así

<?php $foo = array( ''a'' => array( 1 => ''a1'', 2 => ''a2'', 3 => ''a3'' ), ''b'' => array( 1 => ''b1'', 2 => ''b2'', 3 => ''b3'' ), ''c'' => array( 1 => ''c1'', 2 => ''c2'', 3 => ''c3'' ) ); echo "<pre>"; $i=0; foreach ($foo as $val) { $i++; $array[$i] = array_column($foo, $i); } print_r($array); ?>

Resultado:

Array ( [1] => Array ( [0] => a1 [1] => b1 [2] => c1 ) [2] => Array ( [0] => a2 [1] => b2 [2] => c2 ) [3] => Array ( [0] => a3 [1] => b3 [2] => c3 ) )


<?php $tableau_init = [ [ "prenom" => "med", "age" => 1 ], [ "prenom" => "hassan", "age" => 2 ], [ "prenom" => "ali", "age" => 3 ] ]; function transpose($tableau){ $out = array(); foreach ($tableau as $key => $value){ foreach ($value as $subKey => $subValue){ $out[$subKey][$key] = $subValue; } } echo json_encode($out); } transpose($tableau_init);

Prueba como esto


function transpose($array) { array_unshift($array, null); return call_user_func_array(''array_map'', $array); }

O si está utilizando PHP 5.6 o posterior:

function transpose($array) { return array_map(null, ...$array); }