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;
}
9 ответов
просто пройдите массив в правильном порядке. Предполагая, что у вас относительно небольшие массивы, самое простое решение-просто создать новый массив во время этой прогулки.
решение будет иметь вид:
$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);
}
С уважением,
Армандо
измененная версия" принятого " ответа, которая работает намного лучше IMHO:
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));