Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fastest way to reset a multidimensional array?

Say I have a two dimensional array: vectors[x][y], and the initial array structure looks like this:

vectors = [    
 [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,]
]

After some calculations, the data in the array is randomized. What is the fastest way and most efficient way to return the array to it's initial state?

I know that I could just hardcode the above zeroed array and set vectors equal to it again, but I also know that an algorithm such as:

for (var x = 0; x < vectors.length; x++) {
    for (var y = 0; y < vectors[x].length; y++) {
        vectors[x][y] = 0;
    }

}

is O(x * y).

So which is the better way? And is there a better, even faster/more efficient way to solve this?

And for the general case of zeroing a multi-dimensional array of any length, which is the best way? (I'm working in JavaScript if it matters)

like image 255
chrisdotcode Avatar asked Nov 07 '12 18:11

chrisdotcode


2 Answers

Here is my two cents:

I'd go with keeping a clean copy of your original array for fastest performance. You can either keep a referenced hard-coded copy

var vectorsOrig = [    
 [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]
];

or do a dynamic clean clone of the initial array using slice ((recursively in your case for deep copy):

var clonedVectors = [0, 0, 0, 0, 0].slice(0);

Regardless, taking the approach of resetting your vector reference to an original copy will be faster than cycling through and resetting each node. If your old vector array object isn't referenced any more, JavaScript will garbage collect it.

With that said, the question becomes of obtaining a clean copy each and every time. Having once hard-coded instance will give you one clean copy and you'll have to clone it thereafter. Nor do you want to into dynamic generation via similar for loops as the reset option. My advice is to write a clone function that simply returns a new hard-coded or initialized array:

function newVector() {
    return [    
     [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 vector = newVector();
vector[1][2] = 11;
console.dir(vector);
vector = newVector();  // your old array will be garbage-collected if no longer referenced by any other reference
console.dir(vector);

Ideally, it's best to benchmark various approach.

EDIT Thanks to Vega's input, I've modified his test to test three approaches. In Chrome and IE9, this solution seems to be the fastest, in FF (15.0.1) manual iteration seems faster (memory allocation/management slower in FF possibly). http://jsperf.com/array-zero-test/2

like image 52
cbayram Avatar answered Oct 18 '22 11:10

cbayram


So far, it sounds like we have 2 possible choices.

  1. Overwrite the whole thing with zeroes. (Your solution)

  2. Keep a record of all modified elements and only reset those ones. record[0].x = 3; record[0].y = 5; and so on However, you'll still need to loop once through the record. To explain it further, I mean that each time an element in the array is set to a value, you should record that element's placement in the array. Then, using a loop, you can visit each element and set it to 0. So, if you had a sparse array, it would be more efficient.

Depending on the implementation, I can see why you would want #2 instead of #1...but if you seriously have a large enough matrix that you need to worry about analyzing the algorithm, you might consider doing some kind of server pre-processing.

like image 37
0x1F602 Avatar answered Oct 18 '22 10:10

0x1F602