Обычно я спрашиваю, как сделать что-то вроде этого:
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));