如何在PHP中将二维数组旋转90度

14

我想要将一个矩阵顺时针旋转90度。这意味着需要将输入矩阵的第一列变为输出矩阵的第一行,输入矩阵的第二列变为输出矩阵的第二行,而输入矩阵的第三列变为输出矩阵的第三行。需要注意的是,由于进行了90度的旋转,列的底部其实对应了行的开头。

例如:

$matrix=    [[1, 2, 3]
             [4, 5, 6], 
             [7, 8, 9]];

rotate90degrees($matrix)=      [[7, 4, 1],
                                [8, 5, 2],
                                [9, 6, 3]]

我知道的是我需要先转置矩阵,然后交换列来将矩阵旋转90度。如何将其应用于PHP?


你的数据结构是什么?你只想打印出你的新矩阵吗? - Niols
数字,我只想旋转矩阵,正如您在帖子中所看到的。 - Ahmed Safadi
7个回答

13

在回答一个以前的问题时,我向你展示了如何对数组进行转置。要将其旋转90度,请使用转置逻辑,然后依次翻转每行中的值的顺序:

$matrix = [
    [1, 2, 3],
    [4, 5, 6], 
    [7, 8, 9],
];

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

演示


@Gannet - 我在这里提供的类似问题的答案提供了一个解释。 (https://dev59.com/d4rda4cB1Zd3GeqPN446#30082922) - Mark Baker
你可以用以下简单的代码替换掉原来的代码: $matrix = array_map(null, ...$matrix); - lulco

5

另一个可靠的选择:

function rotateMatrix90( $matrix )
{
    $matrix = array_values( $matrix );
    $matrix90 = array();

    // make each new row = reversed old column
    foreach( array_keys( $matrix[0] ) as $column ){
        $matrix90[] = array_reverse( array_column( $matrix, $column ) );
    }

    return $matrix90;
}

远不如@mark-baker聪明,但可能更清晰。

3

PHP没有像“转置”这样的概念,可以在不添加某种线性代数库的情况下对矩阵进行操作。您可以通过遍历矩阵并交换一些索引来原生地实现。

<?php

function rotate90($mat) {
    $height = count($mat);
    $width = count($mat[0]);
    $mat90 = array();

    for ($i = 0; $i < $width; $i++) {
        for ($j = 0; $j < $height; $j++) {
            $mat90[$height - $i - 1][$j] = $mat[$height - $j - 1][$i];
        }
    }

    return $mat90;
}

$mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
print_r($mat);
//123
//456
//789
print_r(rotate90($mat));
//741
//852
//963


$mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9], ["a", "b", "c"]];
print_r($mat);
//123
//456
//789
//abc
print_r(rotate90($mat));
//a741
//b852
//c963

1
如果您想多次旋转矩阵,则需要为外部数组修复键。在“return $mat90;”之前添加“$mat90 = array_values($mat90);”。 - daggerhart

2
你可以使用一行代码简洁地转置矩阵数据。 ... 展开运算符将输入数组的子数组解包成列数据集。在发送到自定义回调函数作用域的数据列上调用 array_reverse()
代码:(演示)
var_export(array_map(fn() => array_reverse(func_get_args()), ...$matrix));

或者:

var_export(array_map(fn(...$col) => array_reverse($col), ...$matrix));

输出(来自任一方):

[[7,4,1],
 [8,5,2],
 [9,6,3]]

0

你可以使用以下代码顺时针旋转矩阵:

function rotateCW($arr){
    return array_map(function($row, $i) use ($arr){
        return array_reverse(array_column($arr, $i));
    }, $arr[0], array_keys($arr[0]));
}

使用以下代码逆时针旋转:

function rotateCCW($arr){
    return array_map(function($row, $i) use ($arr){
        return array_column($arr, count($arr[0]) - 1 -$i);
    }, $arr[0], array_keys($arr[0]));
}

0
function rotate90($a) {
  $cnt = count($a);
  $b = $a;
  
  for ($i = 0; $i < $cnt; $i++) {
    for ($j = 0; $j < $cnt; $j++) {
      $b[$j][$cnt-1-$i] = $a[$i][$j];
    }
  }

  return $b;
}

这段代码片段缺少教育性的解释。 - mickmackusa

0
以下代码使用了额外的空间。
<?php

function rotate90degrees()
{
    $matrix = [[1,2,3],
               [4,5,6],
               [7,8,9]];
               
    $k = 0;
    $len = count($matrix[0]);
    $tmp = [];
    
    // Create a new matrix with [[0,0,0],[0,0,0],[0,0,0]]
    while($k < $len) {
        $row = [];
        $l = 0;
        while($l < $len) {
            $row[] = 0;
            $l++;
        }
        $tmp[] = $row;
        $k++;
    }
    
    // Rotate through the given matrix and fill out the above created new matrix
    for($i=0; $i<$len; $i++) {
        for($j=$len-1; $j>=0; $j--) {
            $tmp[$i][$j] = $matrix[$j][$i];
        }
        $tmp[$i] = array_reverse($tmp[$i]);
    }
    
    return $matrix;
}

以下函数不使用额外的空间。

<?php

function rotate90degreesWithoutAdditionalSpace()
{
    $matrix = [[1,2,3],
               [4,5,6],
               [7,8,9]];
               
    $len = count($matrix);
    
    // Swap the rows columns.
    for($i=0; $i<$len; $i++) {
        for($j=$i; $j<$len; $j++) {
            $tmp = $matrix[$i][$j];
            $matrix[$i][$j] = $matrix[$j][$i];
            $matrix[$j][$i] = $tmp;
        }
    }
    
    // Swap the elements from both ends of each row until the centered element in the row.
    for($i=0; $i<$len; $i++) {
        for($j=0; $j<floor($len/2); $j++) {
            $tmp = $matrix[$i][$j];
            $matrix[$i][$j] = $matrix[$i][$len-1-$j];
            $matrix[$i][$len-1-$j] = $tmp;
        }
    }
    
    return $matrix;
}
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接