PHP - 如何翻转2D数组的行和列

时间:2010-02-08 12:21:10

标签: php arrays multidimensional-array

通常我会问这样的事情:

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

进入这个:

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

11 个答案:

答案 0 :(得分:10)

按正确的顺序走数组。假设您拥有相对较小的阵列,最简单的解决方案就是在行走期间创建一个全新的阵列。

解决方案的形式如下:

$rows = count($arr);
$cols = count($arr[0]); // assumes non empty matrix
$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;
        }
    }
}

答案 1 :(得分:4)

function flip_row_col_array($array) {
    $out = array();
    foreach ($array as  $rowkey => $row) {
        foreach($row as $colkey => $col){
            $out[$colkey][$rowkey]=$col;
        }
    }
    return $out;
}

答案 2 :(得分:2)

我必须编写这个来反转一个名称索引数组的数组。 它对于打印php数组和html表非常有用,因为它甚至用空值填充缺少的元素,因此html表的所有行的数量相同。

  /**
  * Inverses a two dimentional array.
  * The second dimention can be <b>name indexed</b> arrays, that would be preserved.
  * This function is very useful, for example, to print out an html table
  * from a php array.
  * It returns a proper matrix with missing valus filled with null.
  *
  * @param type $arr input 2d array where second dimention can be. <b>name indexed</b>
  * arrays.
  * @return 2d_array returns a proper inverted matrix with missing values filled with
  * nulls
  * @author Nikolay Kitsul
  */
 public static function array_2D_inverse($arr) {
     $out = array();
     $ridx = 0;
     foreach ($arr as $row) {
         foreach ($row as $colidx => $val) {
             while ($ridx > count($out[$colidx]))
                 $out[$colidx][] = null;
             $out[$colidx][] = $val;
         }
         $ridx++;
     }
     $max_width = 0; 
     foreach($out as $v)
          $max_width = ($max_width < count($v)) ? count($v) : $max_width;
     foreach($out as $k => $v){
         while(count($out[$k]) < $max_width)
             $out[$k][] = null;
     }
     return $out;
 }

答案 3 :(得分:2)

您需要的是:

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

答案 4 :(得分:1)

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

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

自从将splat运算符添加到该语言以来,PHP就已经针对此操作采用了一种新颖的本地技术。

需要注意的注意事项是:

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

代码:(Demo

$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的转置技术,同时确保输出的列数与输入的列数相同。

代码:(Demo

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 

代码:(Demo

$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);

答案 5 :(得分:0)

你去吧。有用。 :)



$input1 = array(1,2,3);
$input2 = array(4,5,6);
$input3 = array(7,8,9);
$input4 = array(10,11,12);

$input = array($input1,$input2,$input3,$input4);

echo "\n input array";print_r($input);

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

for($row=0; $row lt 4; $row++)
    for($col=0;$col lt 3;$col++)
        $intern[] = $input[$row][$col];

echo "\n intern ";print_r($intern);

// 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);

答案 6 :(得分:0)

我已经开发了这个代码,部分基于这里找到的解决多维数组的解决方案。

希望它有所帮助!

/**
 *
 * http://stackoverflow.com/questions/2289475/converting-php-array-of-arrays-into-single-array
 * @param array $array
 * @return array
 */
function arrayFlatten(array $array)
{
    $flatten = array();
    array_walk_recursive($array, function($value) use(&$flatten)
    {
        $flatten[] = $value;
    });

    return $flatten;
}

/**
 *
 *  Reorders an array to put the results ordered as a "N", instead of a "Z"  
 *
 * @static
 * @param $array Array to be ordered
 * @param $columns Number of columns of the "N"
 * @return void
 */
function ZOrderToNOrder($array, $columns)
{
    $maxRows = ceil(count($array) / $columns);
    $newArray = array();
    $colCounter = 0;
    $rowCounter = 0;
    foreach ($array as $element)
    {
        $newArray[$rowCounter][] = $element;
        $rowCounter++;
        if ($rowCounter == $maxRows)
        {
            $colCounter++;
            $rowCounter = 0;
        }
    }

    return arrayFlatten($newArray);
}

答案 7 :(得分:0)

falvarez,当一个或多个列有一个或多个其他列(其他> 1)时,ZOrderToNOrder函数无法正常工作。

我认为这段代码可以修复它:

public static function ZOrderToNOrder($array, $columns) {
    $numElements = count($array);

    $maxRows = array();
    for ($i = 0; $i < $columns; $i++) {
        $maxRows[$i] = intval(ceil(($numElements - $i) / $columns));
    }

    $newArray = array();

    $rowCounter = 0;
    $colCounter = 0;
    foreach ($array as $element) {
        $newArray[$rowCounter][$colCounter] = $element;
        $rowCounter++;
        if ($rowCounter === $maxRows[$colCounter]) {
            $rowCounter = 0;
            $colCounter++;
        }
    }

    return self::arrayFlatten($newArray);
}

此致

阿曼

答案 8 :(得分:0)

“已接受”答案的修改版本,效果更好恕我直言:

function array2DFlip($arr) {
 if(!is_array($arr) || count($arr) < 1 || !isset($arr[0])) return array();

 $out = array();

 foreach($arr as $row_id => $row){
    foreach($row as $col_id => $val){
        $out[$col_id][$row_id] = $val;
    }
 }

 return $out;
}

答案 9 :(得分:0)

这个很简单:

$matrix = [
  [1, 2, 3],
  [1, 2, 3],
  [1, 2, 3],
];

$flipped = array_map(function($col, $i) use($matrix){
  return array_map(function($row) use($matrix, $i){
    return $row[$i];
  }, $matrix);
}, $matrix, array_keys($matrix));

答案 10 :(得分:0)

$output_array = [];
foreach ($input_array as $column_id => $rows) {
    foreach ($rows as $row_id => $value) {
        if (!array_key_exists($row_id, $output_array)) {
            $output_array[$row_id] = [];
        }
        $output_array[$row_id][$column_id] = $value;
    }
}

是我通常的解决方案,这只是确保行ID在写入之前作为有效索引存在。这将保留所有键,并将行和列从$ input_array切换到$ output_array