12

通常,我会问如何像这样转换一个 4 行 3 列的数组:

1      2        3
4      5        6
7      8        9
10    11       12

进入一个 3 行 4 列的数组,例如:(我不想要这个

1   4   7   10
2   5   8   11
3   6   9   12

但实际上,我想把它变成这样:(我想要这个

1   5   9
2   6   10
3   7   11
4   8   12

换句话说,我想翻转行和列,但保持新数组的“宽度”和“高度”相同。我已经坚持了一个多小时。

这是我用来进行正常“翻转”的函数(第一个示例):

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

4 回答 4

11

只需按照正确的顺序遍历数组即可。假设您有相对较小的阵列,最简单的解决方案就是在遍历期间创建一个全新的阵列。

解决方案将采用以下形式:

$rows = count($arr);
$ridx = 0;
$cidx = 0;

$out = array();

foreach($arr as $rowidx => $row){
    foreach($row as $colidx => $val){
        $out[$ridx][$cidx] = $val;
        $ridx++;
        if($ridx >= $rows){
            $cidx++;
            $ridx = 0;
        }
    }
}
于 2010-02-08T12:27:30.973 回答
3
function flip_row_col_array($array) {
    $out = array();
    foreach ($array as  $rowkey => $row) {
        foreach($row as $colkey => $col){
            $out[$colkey][$rowkey]=$col;
        }
    }
    return $out;
}
于 2013-02-28T08:39:40.680 回答
1

首先,你不想要什么(这是你想要的解决方案的一半)......

“翻转行和列”的术语是“转置”。

自从 splat 运算符被添加到语言中以来,PHP 就为这个动作提供了一种时尚的原生技术。

要记住的警告是:

  1. 所有键都必须是数字。splat/spread 运算符将阻塞非数字键。
  2. 矩阵必须是完整的。如果有任何差距,您可能无法得到您想要的结果。

代码:(演示

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

var_export(
    array_map(null, ...$matrix)
);

输出:

[
    [1, 4, 7, 10],
    [2, 5, 8, 11],
    [3, 6, 9, 12],
];

现在,为了你想要的!

这是一个功能风格的片段,它结合了 php 的转置技术,同时确保输出与输入具有相同的列数。

代码:(演示

var_export(
    array_map(
        null,
        ...array_chunk(
            array_merge(...$matrix),
            count($matrix)
        )
    )
);

输出:

[
    [1, 5, 9],
    [2, 6, 10],
    [3, 7, 11],
    [4, 8, 12],
];

这种方法将输入展平,然后将其分成长度等于原始行数的行,然后转置该结果。


后期编辑:作为纯粹的学术追求,我想看看不使用任何条件且不维护多个“计数器”的纯数学技术会是什么样子。

事实证明,因为 php 数组会将浮点键截断为整数,所以这可以在单个循环中完成。

// assuming the earlier mentioned 3x4 matrix:
i    old pos   new pos  i%rows  i/rows  i/col   i%col  
0  : [0][0] => [0][0]     0      0       0        0
1  : [1][0] => [0][1]     1      0.25    0.3      1
2  : [2][0] => [0][2]     2      0.5     0.6      2
3  : [3][0] => [1][0]     3      0.75    1        0
4  : [0][1] => [1][1]     0      1       1.3      1
5  : [1][1] => [1][2]     1      1.25    1.6      2
6  : [2][1] => [2][0]     2      1.5     2        0
7  : [3][1] => [2][1]     3      1.75    2.3      1
8  : [0][2] => [2][2]     0      2       2.6      2
9  : [1][2] => [3][0]     1      2.25    3        0
10 : [2][2] => [3][1]     2      2.5     3.3      1
11 : [3][2] => [3][2]     3      2.75    3.6      2 

代码:(演示

$rows = count($matrix);
$cols = count(current($matrix));
$cells = $rows * $cols;

$result = $matrix;  // used to preserve original key orders
for ($i = 0; $i < $cells; ++$i) {
    $result[$i % $rows][$i / $rows] = $matrix[$i / $cols][$i % $cols];
}
var_export($result);
于 2020-12-08T10:48:10.567 回答
0

干得好。有用。:)

示范

$input = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
    [10, 11, 12],
];

// flipping matrices
$output = array();
$intern = array();

for($row=0; $row < 4; $row++)
    for($col=0;$col < 3;$col++)
        $intern[] = $input[$row][$col];
    
// nesting the array
$count = 0;
$subcount = 0;

foreach($intern as $value)
{

    $output[$count][$subcount] = $value;
    $count++;

    if($subcount == 3)
    {
        break;
    }

    if($count == 4)
    {
        $count = 0;
        $subcount++;
    }
}


echo "\n final output ";print_r($output);
于 2010-02-08T13:35:35.283 回答