PHP – как перевернуть строки и столбцы 2D-массива

Обычно я спрашиваю, как сделать что-то вроде этого:

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

Просто пройдите массив в правильном порядке. Предполагая, что у вас относительно небольшие массивы, самым простым решением является создание совершенно нового массива во время этой прогулки.

Решение будет иметь вид:

 $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; } } } 
 function flip_row_col_array($array) { $out = array(); foreach ($array as $rowkey => $row) { foreach($row as $colkey => $col){ $out[$colkey][$rowkey]=$col; } } return $out; } 

Я должен был написать это, чтобы инвертировать массив индексированных имен массивов. Это очень полезно для печати 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; } 

Что вам нужно:

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

Ну вот. Оно работает. 🙂

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

Я разработал этот код, частично основанный на найденном здесь решении сгладить многомерные массивы.

Надеюсь, поможет!

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

falvarez, функция ZOrderToNOrder работает некорректно, если один или несколько столбцов имеют еще один элемент, который содержит другие столбцы (другие> 1).

Я думаю, что этот код исправить:

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

С Уважением,

Armando

Модифицированная версия «принятого» ответа, который работает БОЛЬШЕ лучше ИМХО:

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

Получил этот простой:

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