3

我已经问过一个类似的问题,但我需要不同的效果。原来的问题在这里


我有一个简单的数组。数组长度始终是平方数。所以 16、25、36 等等。

$array = array('1', '2', '3', '4' ... '25');

我所做的是用 HTML 排列数组,使其看起来像一个具有均匀边的块。

我想要做的是对元素进行排序,这样当我将 JSON 编码的数组传递给 jQuery 时,它将迭代数组,淡入当前块,所以我会得到一个循环动画。所以我想像这样对数组进行排序

所以我的排序数组看起来像

$sorted = array('1', '6', '11'', '16', '21', '22', '23' .. '13');

有没有办法这样做?..谢谢


编辑:

我试图通过创建类似矩阵的列/行数组来做到这一点:

$side = 5;

$elems = $side*$side;
$array = range(1,$elems);

for($i=1; $i <= $side; $i++) {
   for($x=$i; $x <= $elems; $x=$x+$side) {
      $columns[$i][] = $x; 
   }
}

for($i=1, $y=1; $i <= $elems; $i=$i+$side, $y++) {
   for($x=$i; $x < $side+$i; $x++) {
      $rows[$y][] = $x;
   }
}

我的下一步是走第一列,最后如果它在最后一个元素列上,最后在最后一个元素上等等。如果有人有更好的主意,那就太好了:)

4

4 回答 4

1

只要网格始终是方形的,这将起作用:

<?php

    // The size of the grid - 5x5 in the example above
    $gridSize = 5;

    // Create a 2D array representing the grid
    $elements = array_chunk(range(1, pow($gridSize, 2)), $gridSize);

    // Find the half way point - this will be the end of the loop since we
    // want to stop in the middle
    $end = ceil($gridSize / 2);

    // An array to hold the result    
    $result = array();

    // The stopping point of the current interation
    $stop = $gridSize;

    // Loop from start to the middle
    for ($i = 0; $i < $end; $i++) {

        // start in the top left corner
        $x = $y = $i;

        // Traverse Y top to bottom
        while ($y < $stop) {
            $result[] = $elements[$y++][$x];
        }
        $y--;
        $x++;

        // Traverse X left to right
        while ($x < $stop) {
            $result[] = $elements[$y][$x++];
        }
        $x--;
        $y--;

        // Traverse Y bottom to top
        while ($y >= $gridSize - $stop) {
            $result[] = $elements[$y--][$x];
        }
        $y++;
        $x--;

        // Make sure we come in a level
        $stop--;

        // Traverse X right to left
        while ($x >= $gridSize - $stop) {
            $result[] = $elements[$y][$x--];
        }
    }

    print_r($result);

看到它工作

于 2013-03-04T14:59:44.070 回答
0

这应该有效。您可以将任何数组传递给 circularSort 函数,它将返回您的排序数组。

/*
Get the circular sorted array
*/
function circularSort($array)
{
    //Get the length of array
    $arrayLength = count($array);
    //Find the square root of length of array
    $arrayRows = sqrt($arrayLength);

    //Divide the arrays in $arrayRows
    $arrayChunks = array_chunk($array,$arrayRows);
    $circularArray = array();

    //Call Circular Array function .. Result will be stored in $circularArray
    circularArray($arrayChunks,$circularArray);
    return $circularArray;
}

/*
Loop arrayChunk in following order
1. Fetch first item from each chunks
2. Fetch all items from last chunk and remove that array from arrayChunk
3. Reverse elements in each remaining chunk
4. Reverse entire arrayChunk array
5. Repeat above 4 steps until $arrayChunks is empty
*/
function circularArray(&$arrayChunks, &$circularArray)
{
    if(empty($arrayChunks))
    {
        return true;
    }

    //1. Fetch first item from each chunks
    foreach($arrayChunks as &$arrayChunk)
    {
        $circularArray[] = array_shift($arrayChunk);
    }

    //Fetch Last Chunk from array
    $lastChunk = array_pop($arrayChunks);

    //2. Fetch all items from last chunk and remove that array from arrayChunk
    foreach($lastChunk as $chunkElement)
    {
        $circularArray[] = $chunkElement;
    }

    //3. Reverse elements in each remaining chunk
    foreach($arrayChunks as &$arrayChunk)
    {  
        if (is_array($arrayChunk))
        {    
            $arrayChunk = array_reverse($arrayChunk);
        }
    }

    $arrayChunks = array_reverse($arrayChunks);

    return circularArray(&$arrayChunks, &$circularArray);
}

例如

$array = range(1, 25);
$circularArray = circularSort($array);
于 2013-03-04T15:08:41.510 回答
0

O(n) 中的另一种方法:

<?php
function circ_sort ($inArray) {

    $rowSize = pow(count($inArray), 0.5);
    if((int)$rowSize != $rowSize) {
        throw new InvalidArgumentException();
    }
    $rowSize = (int)$rowSize;

    $round =-1;
    for ($x =-1, $y=0, $count =0; $count < count($inArray);) {

        if ($y > $x) {
            if ($x +1 == $y) {
                $direction = 'D';   //Down
                $round ++;
                $max_iter = $rowSize - (2 * $round);
            } else {
                $direction = 'L'; //Left
                $max_iter = $y - $x -1;
            }
        } else if ($x > $y) {
            $direction = 'R'; //Right
            $max_iter = $rowSize - (2 * $round) -1;

        } else if ($x == $y) {
            $direction = 'U'; //Up
            $max_iter = $rowSize - (2 * $round) -1;

        }

        switch ($direction) {
            case 'D':   //Down
                for ($iter =0; $iter < $max_iter; $iter++) {
                    $x++;
                    $circArray[] = $inArray[$x*$rowSize + $y];
                    $count++;
                }
                break;
            case 'R': //Right
                for ($iter =0; $iter < $max_iter; $iter++) {
                    $y++;
                    $circArray[] = $inArray[$x*$rowSize + $y];
                    $count++;
                }
                break;
            case 'U':   //Up
                for ($iter =0; $iter < $max_iter; $iter++) {
                    $x--;
                    $circArray[] = $inArray[$x*$rowSize + $y];
                    $count++;
                }
                break;
            case 'L':   //Left
                for ($iter =0; $iter < $max_iter; $iter++) {
                    $y--;
                    $circArray[] = $inArray[$x*$rowSize + $y];
                    $count++;
                }
                break;
        }
    }
    return ($circArray);
}

$array = range(1, 25);
$circ_array = circ_sort($array);

var_dump($circ_array);

?>
于 2013-03-04T17:45:03.993 回答
0

我的解决方案:

诀窍是:第一次运行是 5,然后是 4 个元素的两个运行,3 个元素的两个,2 个元素的 2 个和 1 个元素的两个。(5,4,4,3,3,2,2,1,1) 在每次运行中,它都会增加一个状态模块 4。根据状态,运行会朝一个方向或另一个方向前进。

这是代码:

function circularSort(array $array) {
    $n2=count($array);
    $n=sqrt($n2);
    if((int)$n != $n) throw new InvalidArgumentException();

    $Result = Array();
    $run =$n; $dir=1;
    $x=0; $y=-1;
    $i=0;
    $st=0;
    while ($run) {
        while ($dir) {
            for ($j=0; $j<$run; $j++) {

                if ($st==0) $y++;
                if ($st==1) $x++;
                if ($st==2) $y--;
                if ($st==3) $x--;

                $p=$y * $n +$x;
                array_push($Result,$array[$p]);

            }
            $st = ($st +1) & 3;
            $dir--;
        }

        $dir=2;
        $run--;
    } 

    return $Result;
}

$a = range(1,25);
var_dump(circularSort($a));
于 2013-03-06T16:58:42.917 回答