对多维数组进行排序,并将所有相同的值移动到as3中的最后一个数组

时间:2013-06-11 02:32:20

标签: actionscript-3 sorting multidimensional-array

我目前正在处理库存的原始图形 这显示了目前占用了多少空间以及多少空间 左

它通过显示5行20个正方形来实现 (灰色=自由空间,黄色=占用空间)。

现在,我的问题是我想找到所有的值 是1并将它们放在最后一个数组中。

这样阵列来自:

var myMap:Array = [
            [1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
            [1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
            [1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0],
            [1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0],
            [1,0,0,0,0,0,1,1,0,1,1,0,0,1,1,0,0,0,0,0]
            ];

   var myMap:Array = [
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
            ];

基本上我想对整个数组进行排序,以便所有零首先出现 并且所有1都被放入最后一个直到它完整,然后是第二个最后一个,依此类推。

我离开了我很可能需要一个算法,但我希望有一个更简单的方法来做到这一点。我通常是C#开发人员,因此AS3不是我最强的套装。

希望有人明白我的意思,可以帮助我,早上4:30,所以我可能不会像我想的那样清醒。

〜感谢

修改

添加了代码,以便人们可以获得更多信息:

请记住,大多数名称等都是占位符,目前我只是需要它才能正常工作。

private function _showInventoryGraphic()
        {
            var mapWidth = 20;
            var mapHeight = 5;
            var myMap:Array = [
            [1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
            [1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
            [1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0],
            [1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0],
            [1,0,0,0,0,0,1,1,0,1,1,0,0,1,1,0,0,0,0,0]
            ];
            var posX:int = 15;
            var posY:int = 15;
            var startPosY:int = 250;
            for (var i:int=0; i<mapHeight; i++)
            {
                for (var u:int = 0; u < mapWidth; u++)
                {
                    if (myMap[i][u] == 0)
                    {
                        var grayRect:Shape = new Shape;
                        grayRect.graphics.beginFill(0x808080);
                        grayRect.graphics.drawRect(posX*u, startPosY, 10,10);
                        grayRect.graphics.endFill();
                        addChild(grayRect);
                    }
                    if (myMap[i][u] == 1)
                    {
                        var yellowRect:Shape = new Shape;
                        yellowRect.graphics.beginFill(0xFFFF00);
                        yellowRect.graphics.drawRect(posX*u, startPosY, 10,10);
                        yellowRect.graphics.endFill();
                        addChild(yellowRect);
                    }
                }
                startPosY += posY;
            }

        }

1 个答案:

答案 0 :(得分:2)

从几种不同的方法中尝试后,我认为最大的挑战是它是一个二维阵列。

第一次尝试是类似的,但是像quicksort一样,在2d数组的任何一端都有2个指针,他们向内“移动”,寻找第一个指针为'1'且最后一个指针为a的情况'0'并交换两个,直到指针在'middle'中相遇。我试图在二维数组中正确递减和递增线性计数器时放弃了这种方法。 = B

第二次尝试是通过跟踪数组中最后一个为空的索引以及数组中最后一个已满的索引。然后在addItem和removeItem方法中,我将项目放在正确的位置并更新计数器以避免排序。这似乎有效,但可能有点混乱,未来可能难以维护。它将结果排序在单独的数组中。

在“直接排序”的第三次尝试中,我认为最简单的方法就是将阵列分成2d阵列​​,对其进行排序,然后重新加入。你是正确的,因为这不是最有效的方法,但要考虑的一件事是需要运行的频率以及它在实际情况下需要的效率。我认为只有100个元素的二维数组使用效率低的排序方法并不是一个大问题?

也许其他人可以提出更好/更清洁的方法。 = B

以下是我提到的代码。

第二次尝试(注意:我没有完全测试这个,但似乎有效):

import flash.geom.Point;

var unsortedMap:Array = [
                         [0,0,0,0,0,0,0,0,0,0],
                         [0,0,0,0,0,0,0,0,0,0],
                         [0,0,0,0,0,0,0,0,0,0],
                         [0,0,0,0,0,0,0,0,0,0],
                         [0,0,0,0,0,0,0,0,0,0]
                        ];

var sortedMap:Array = [
                         [0,0,0,0,0,0,0,0,0,0],
                         [0,0,0,0,0,0,0,0,0,0],
                         [0,0,0,0,0,0,0,0,0,0],
                         [0,0,0,0,0,0,0,0,0,0],
                         [0,0,0,0,0,0,0,0,0,0]
                        ];

var rowSize:int = unsortedMap[0].length;
var rowCount:int = unsortedMap.length;

// points to the last index at start, since want to have filled items at the 'end'
var emptySpotPointer:Point = new Point(rowSize - 1, rowCount - 1);
var fullSpotPointer:Point = new Point(rowSize - 1, rowCount - 1);

function print2dArray(prefix:String, input:Array):void {
    trace(prefix);
    for(var row:String in input){
        trace("\t"+ input[row]);
    }
    trace("");
}


function addItem(inputX:int, inputY:int):void {
    if(unsortedMap[inputY][inputX] == 1){
        trace("addItem() - Already an item here: "+ inputX +", "+ inputY);
        return;
    }
    trace("addItem() - Adding an item: "+ inputX +", "+ inputY);

    unsortedMap[inputY][inputX] = 1;
    sortedMap[emptySpotPointer.y][emptySpotPointer.x] = 1;
    fullSpotPointer.x = emptySpotPointer.x;
    fullSpotPointer.y = emptySpotPointer.y;

    if(emptySpotPointer.x == 0){
        emptySpotPointer.x = rowSize - 1;
        emptySpotPointer.y--;

    } else {
        emptySpotPointer.x--;
    }
}


function removeItem(inputX:int, inputY:int):void {
    if(unsortedMap[inputY][inputX] == 0){
        trace("removeItem() - No item here to remove: "+ inputX +", "+ inputY);
        return;
    }
    trace("removeItem() - Removing an item here: "+ inputX +", "+ inputY);

    unsortedMap[inputY][inputX] = 0;
    sortedMap[fullSpotPointer.y][fullSpotPointer.x] = 0;

    if(fullSpotPointer.x == (rowSize - 1)){
        fullSpotPointer.x = 0;
        fullSpotPointer.y++;

    } else {
        fullSpotPointer.x++;
    }
}



// testing stuff here
// -----------------------------------------------------------------
function addRandomitems():void {
    var randomX:int = Math.floor(Math.random() * rowSize);
    var randomY:int = Math.floor(Math.random() * rowCount);
    addItem(randomX, randomY);
}

function removeRandomitems():void {
    var randomX:int = Math.floor(Math.random() * rowSize);
    var randomY:int = Math.floor(Math.random() * rowCount);
    removeItem(randomX, randomY);
}

print2dArray("unsortedMap", unsortedMap);
print2dArray("sortedMap", sortedMap);

trace("Test: Adding items now ---------------------");
var counter:int = 0;
for(counter = 0; counter < 50; counter++){
    addRandomitems();
    print2dArray("unsortedMap", unsortedMap);
    print2dArray("sortedMap", sortedMap);
}

trace("Test: Removing items now ---------------------");
for(counter = 0; counter < 50; counter++){
    removeRandomitems();
    print2dArray("unsortedMap", unsortedMap);
    print2dArray("sortedMap", sortedMap);
}

第三次尝试:

import flash.utils.getTimer;

var myMap:Array = [
            [1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
            [1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
            [1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0],
            [1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0],
            [1,0,0,0,0,0,1,1,0,1,1,0,0,1,1,0,0,0,0,0]
            ];

function sort(inputArray:Array):Array {
    var rowSize:int = inputArray[0].length;

    var flat:Array = new Array();

    // flattening the array here
    for(var row:String in inputArray){
        flat = flat.concat(inputArray[row]);
    }
    flat.sort();

    var result:Array = new Array();

    // recreating the original array here by cutting out 'rowSize' chunks and reforming the 2d array
    while(flat.length > 0){
        result.push(new Array(flat.splice(0, rowSize)));
    }
    return result;
}

// testing
var startTimer:int = flash.utils.getTimer();
for(var counter:int = 0; counter < 10000; counter++){
    sort(myMap);
}

// Running the above 10,000 times takes 1836ms for me.
trace(flash.utils.getTimer() - startTimer);

// just to see the output:
trace(sort(myMap).join("\n"));