3
\$\begingroup\$

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.

rolfl
98.1k17 gold badges219 silver badges419 bronze badges
asked Mar 25, 2014 at 19:57
\$\endgroup\$
1
  • \$\begingroup\$ Are you always dealing with just 0s and 1s? \$\endgroup\$ Commented Mar 25, 2014 at 22:55

1 Answer 1

2
\$\begingroup\$

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.

answered Mar 25, 2014 at 20:12
\$\endgroup\$
3
  • 1
    \$\begingroup\$ 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? \$\endgroup\$ Commented Mar 25, 2014 at 20:39
  • \$\begingroup\$ Updated question. \$\endgroup\$ Commented Mar 25, 2014 at 21:01
  • \$\begingroup\$ Thanks for the great answer! I'll stick to these suggestions. \$\endgroup\$ Commented Mar 27, 2014 at 9:26

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.