Reputation: 5028
What is the most efficient way to invert an arbitrary length binary array? I.e. set 1 = 0 and 0 = 1 for all 0, 1 in the array.
var arr1 = [ 0, 0, 1, 1, 1, 0, ..., 1 ];
Upvotes: 1
Views: 416
Reputation: 47619
Since this seems to have turned into a contest, what about using Typed Arrays?
// Construct an array of length 1024
var length = 1024;
var arr = [];
for (var i = 0; i < length; i++) {
arr.push(Math.random() > 0.5 ? 1 : 0);
}
var typedLoop = function() {
var typed = new Uint8Array(arr);
for (var i = 0; i < typed.length; i++) {
typed[i] = (typed[i] == 0 ? 1 : 0);
}
return arr;
}
var untypedLoop = function() {
for (var i = 0; i < arr.length; i++) {
arr[i] = (arr[i] == 0 ? 1 : 0);
}
return arr;
}
var withClosure = function() {
return arr.map(function(x) { return x === 0 ? 1 : 0; });
}
// A time-elapsed function with a lot of repetitions
var reps = 10000;
var time = function(f) {
var before = new Date().getTime();
for(var i = 0; i < reps; i++) {
f();
}
console.log(new Date().getTime() - before);
}
Some results:
time(typedLoop)
212
time(untypedLoop)
6169
time(withClosure)
601
I think that's really interesting. Using a typed array is the shortest. Using a closure with normal array takes 3x as long. Using the for loop is 30x. On my machine, now, with this release of this browser at this ambient temperature and the wind blowing northerly.
Using elapsed time isn't a very good measure at all but it's a practical indication.
Obviously this doesn't matter at all. You probably won't be calculating thousand-long arrays tens of thousands of times. Go with the clearest code. But it does answer your question about the 'most efficient' (which isn't always the best).
Upvotes: 0
Reputation: 207521
This is very inefficient, but a fun way to attack the problem.
var arr1 = [ 0, 0, 1, 1, 1, 0, 1 ];
var swapped = JSON.parse(JSON.stringify(arr1).replace(/[01]/g, function(x){ return x==0?1:0;}));
Written as multiple lines:
var arr1 = [ 0, 0, 1, 1, 1, 0, 1 ];
var arrayString = JSON.stringify(arr1);
var flip1and0 = arrayString.replace(/[01]/g, function(x){ return x==0?1:0;});
var swappedArray = JSON.parse(flip1and0);
Upvotes: 2
Reputation: 239493
Using a binary operation should be faster than any other approach.
var arr1 = [ 0, 0, 1, 1, 1, 0, 1 ];
for (var i = 0; i < arr1.length; i += 1) {
arr1[i] ^= 1;
}
console.log(arr1);
# [ 1, 1, 0, 0, 0, 1, 0 ]
We use Binary XOR with 2. It works because
console.log(1 ^ 1); // 0
console.log(0 ^ 1); // 1
Upvotes: 3
Reputation: 1074495
In general, "efficiency" questions in JavaScript are a pitfall, because different engines are more efficient with different things. Optimizing before there's a problem to solve is almost always a waste of time (regardless of language/environment), but this is particularly true when your optimization targets (JavaScript engines) vary markedly in their performance profiles.
In general, subject to that caveat, I don't think you'll find anything more efficient than a simple for
loop where you cache the length.
var arr1 = [ 0, 0, 1, 1, 1, 0, ..., 1 ];
var n, l;
for (n = 0, l = arr1.length; n < l; ++n) {
arr1[n] = arr1[n] === 0 ? 1 : 0;
}
But again, solve performance issues when you run into performance issues, and then solve them by testing in your target environments (either within your app, or with tools like http://jsperf.com).
Upvotes: 3
Reputation: 30993
You can try with a for loop.
Code:
var arr1 = [0, 0, 1, 1, 1, 0, 1];
for (var i = 0; i < arr1.length; i++) {
arr1[i] = 1 - arr1[i]
}
At the moment binary operation win: http://jsperf.com/test-foor-loop
Demo: http://jsfiddle.net/IrvinDominin/Kw3e6/
Upvotes: 0