# Shift data in multidimensional array

I'm currently facing a problem where I have to shift data in a multidimensional JS array in different directions, but I think the first solution I whipped up is not as efficient as it could be (some fancy math I don't know of maybe?).

Let me explain the problem a bit better with some examples of my data.

This is the array in question:

[1][0][1][0][1][0]
[0][1][1][0][0][0]
[0][0][1][0][1][1]
[0][0][0][0][1][1]
[0][0][1][1][0][0]
[1][0][0][1][1][1]


If I shifted it to the left, it should look like this:

[1][1][1][0][0][0]
[1][1][0][0][0][0]
[1][1][1][0][0][0]
[1][1][0][0][0][0]
[1][1][0][0][0][0]
[1][1][1][1][0][0]


Or down

[0][0][0][0][0][0]
[0][0][0][0][0][0]
[0][0][1][0][1][0]
[0][0][1][0][1][1]
[1][0][1][1][1][1]
[1][1][1][1][1][1]


To put it simple - shift 1's as far as possible.

The code I wrote is fairly simple

for (w = 0; w < arraySize; w++) {
for (h = 0; h < arraySize; h++) {
tiles = $('.arrayContainer .row').eq(w).children(); if (tiles.eq(h).html() != "" && tiles.eq(h - 1).html() == "" && (h-1) >= 0) { tiles.eq(h - 1).html(tiles.eq(h).html()); tiles.eq(h).html(""); } } }  This will shift values left-to-right by one step. arraySize is the variable that determines the size of the array, tiles gets each row of the array output. If I wasn't here, posting and wouldn't think this could be done better I'd create four of these structures and just live with it, but I'm pretty sure this can be done better. • Are you always dealing with just 0s and 1s? Commented Mar 25, 2014 at 22:55 ## 1 Answer From a once over: • You should consider MVC, your data should live in an object you created, you should update your model, and then from your model update the UI • If you dont want to do this, then you should at least find all cells and assign each cell to a 2d JS array var tiles = []; for (w = 0; w < arraySize; w++) { tiles[w] = []; for (h = 0; h < arraySize; h++) { tiles[w][h] =$('.arrayContainer .row').eq(w).children().eq(h);
}
}


Otherwise you are executing \$('.arrayContainer .row') far too many times, and that operation takes a lot of time, then you can do your logic like this:

for (w = 0; w < arraySize; w++) {
for (h = 0; h < arraySize; h++) {
tile = tiles[w][h]
if (tile.html() != '' && tiles[w][h-1].html() == '' && (h-1) >= 0) {
tiles[w][h-1].html(tile.html());
tile.html('');
}
}
}


You could consider assigning tiles[w][h-1] to a variable as well to make it more readable

• Consider c and r as variables ( column and row if you are feeling verbose ). Those are better names than height and width.

• I hope you declared tiles with var somewhere else, otherwise you have global namespace pollution.

• As for not having to repeat the same 2 loops for every direction, you could think about passing a columnDelta and RowDelta ( for your 2 loops, columnDelta would be -1, rowDelta would be 0 ) I am not sure it is worth it, since you only have 4 cardinal directions, up to you.

• Thanks for all the great suggestions, they truly make sense. What about the for loops, though. Is there any way to avoid creating this structure for every direction I want the data to be shifted? Commented Mar 25, 2014 at 20:39
• Updated question. Commented Mar 25, 2014 at 21:01
• Thanks for the great answer! I'll stick to these suggestions. Commented Mar 27, 2014 at 9:26