Home » Php » arrays – create transpose matrix using php

arrays – create transpose matrix using php

Posted by: admin July 12, 2020 Leave a comment

Questions:

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

?>
How to&Answers:

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

Answer:

I believe this works with rectangular arrays as well.
The trick: return array_map(null, ...$squareArray); seems to work in an unexpected way for a single column array

function RotateSquare2DArray($squareArray) 
{

    if ($squareArray == null) { return null; }
    $rotatedArray = array();
    $r = 0;

    foreach($squareArray as $row) {
        $c = 0;
        if (is_array($row)) {
            foreach($row as $cell) {
                $rotatedArray[$c][$r] = $cell;
                ++$c;
            }
        }
        else $rotatedArray[$c][$r] = $row;
        ++$r;
    }
    return $rotatedArray;
}

If the array is associative, I use this

function RotateSquareAssociativeArray($squareArray)
{
    if ($squareArray == null) { return null; }
    $rotatedArray = array();
    $r = 0;

    foreach($squareArray as $c=>$row) {
        if (is_array($row)) {
            foreach($row as $key=>$cell) {
                $rotatedArray[$key][$c] = $cell;
            }
        }
        else {
            $rotatedArray[$c][$r] = $row;
        }
        ++$r;
    }
    return $rotatedArray;
}