Safad Funy Safad Funy - 3 months ago 31
PHP Question

create transpose matrix using php

For example if a matrix is:

1 2
3 4
5 6


Then transpose of above matrix will be:

1 3 5
2 4 6


This is my current code:

<?php

// transpose matrix
$trans = array(
array(1, 2),
array(3, 4),
array(5, 6)
);

foreach ($trans as $key => $val){
foreach ($trans[$key] as $k => $v){
echo $v;
}
}

?>

Answer

There's a quirky PHP way to transpose a 2d array:

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

array_unshift($trans, null);
$trans = call_user_func_array('array_map', $trans);
var_dump($trans);

Demo

EDIT Easier approach using PHP 5.6 array unpacking

With the introduction of the array argument unpacking feature in PHP 5.6, we can simplify this still further:

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

$trans = array_map(null, ...$trans);
var_dump($trans);

EDIT Explanation

Quoting from the PHP docs for the array_map() function:

An interesting use of this function is to construct an array of arrays, which can be easily performed by using NULL as the name of the callback function

(See Example #4 from that docs page for an example of what this does)

The array_unshift($trans, null) that we perform first is providing that NULL callback, and we use call_user_func_array() because we don't necessarily know how many values there are in our $trans array. What we're doing using that call_user_func_array() is the equivalent of:

$trans = array_map(NULL, $trans[0], $trans[1], $trans[2]);

for your example array, because the top-level of your 2-d array has three elements (keys 0, 1 and 2).

Effectively, this NULL callback loops through all the arrays in parallel taking each value from them in turn to build a new array:

$maxArraySize = max(count($array[0], $array[1], $array[2]);
// $maxArraySize will have a value of 2 in your case,
//     because your sub-arrays are all equal size
$newArray = [];
for($i = 0; $i < $maxArraySize; ++$i) {
    $tmpArray = [];
    $tmpArray[] = $array[0][$i];
    $tmpArray[] = $array[1][$i];
    $tmpArray[] = $array[2][$i];
    $newArray[] = $tmpArray[];
}

There's a couple of extra checks in there

  • it doesn't care if your arrays are associative or enumerated in either dimension, because it accesses the $ith element, not the index
  • If the sub-arrays aren't all the same length, then it effectively pads the shorter sub-arrays with null values to match the length of the longest
  • It doesn't matter how many arrays you pass in, it will work with them all in parallel