What can be the most efficient way to find an item in an array, which is logical and understood by a web developer?
I came across this piece of code:
var inArray = function(a, b, c, d) {
for (c in b) d |= b[c] === a;
return !!d
};
It works fine. Can someone please explain me the code?
I also came across an exact same question that might make mine as a duplicate. But my real question lies in explanation of the above code and why bitwise operator has been used into it.
Also, can there be a way without any for loop, or iteration to get index of an item in an Array?
4 Answers 4
var inArray = function(a, b, c, d) {
for (c in b) d |= b[c] === a;
return !!d
};
That is some terrible code, and you should run away from it. Bitwise operators are completely unnecessary here, and c and d being parameters makes no sense at all (as Raymond Chen pointed out, the author of the code likely did it to safe space of declaring local variables -- the problem though is that if true is passed in for d the code is suddenly broken, and the extra parameters destroys any sense of understanding that glancing at the declaration would provide).
I'll explain the code, but first, here's a better option:
function inArray(arr, obj) {
for (var i = 0; i < arr.length; ++i) {
if (arr[i] === obj) {
return true;
}
}
return false;
}
Note that this is dependent on the array being an actual array. You could use a for (k in arr) type loop to generalize it to all objects.
Anyway, on to the explanation:
for (c in b) d |= b[c] === a;
This means that for every key in b (stored in c), we will check if b[c] === a. In other words, we're doing a linear scan over the array and checking each element against a.
d |= val is a bitwise or. The bits that are high in val will be set high in d. This is easier to illustrate in languages where bits are more exposed than in JS, but a simple illustration of it:
10011011
01000001
--------
11011011
It's just OR'ing each individual bit with the same location bit in the other value.
The reason it's an abuse here is that it convolutes the code and it depends on weird implicit casts.
x === y returns a boolean. A boolean being used in a bitwise expression makes little sense. What's happening though is that the boolean is being converted to a non-zero value (probably 1).
Similarly, undefined is what d will be. This means that d will be cast to 0 for the bitwise stuff.
0 | 0 = 0, but 0 | 1 = 1. So basically it's a glorified:
for (c in b) d = (d || (b[c] === a));
As for !!x that is just used to cast something to a bool. !x will take x, implicitly cast it to a bool and then negate it. The extra ! will then negate that again. Thus, it's likely implicitly casting to a bool (!!x being true implies that x is at least loosely true (1, "string", etc), and !!x implies that x is at least loosely false (0, "", etc).
This answer offers a few more options. Note though that all of them are meant to fallback to the native indexOf that will almost certainly be faster than anything we can code in script-land.
2 Comments
This code is pretty poorly written, and barely readable. I wouldn't qualify it as "awesome"...
Here's a rewritten version, hopefully more readable:
function inArray (aElt, aArray) {
var key;
var ret = false;
for (key in aArray)
ret = ret || (aArray[key] === aElt);
return ret;
}
The for loop seems like the most natural way to do that. You could do it recursively but that doesn't feel like the easiest approach here.
9 Comments
=== can only evaluate to true or false, which map to 1 and 0 as numbers. For that limited range of values, | and || are effectively identical (except for short-circuit evaluation).var inArray = function(a,b,c,d){for(c in b)d|=b[c]===a;return!!d }; modified to look good by some mod just now. It being one-liner made me look at it as awesome may beindexOf function.What can be the most efficient way to find an item in an array, which is logical and understood by a web developer?
Either the native method, haystack.indexOf(needle) !== -1 or a looped method which returns as soon as it can
function inArray(needle, haystack) {
var i = haystack.length;
while (i) if (haystack[--i] === needle) return true;
return false;
};
9 Comments
C style while loop. A for loop would be a lot more readable, though that is of course just opinion.while is very fast and n !== 0 == truefor loop is essentially a while loop. Computers have no concept of a for loop (or even a while loop). A similarly constructed for loop, or even while (i > 0) is going to have identical performance (or perhaps so little difference that it is truly negligible by any comparison). I'm just being picky (and obnoxiously opinionated) though :-). Either way, +1.while differently to for so you can sometimes squeeze a tiny bit more if you choose a while. You are right though, the difference is minimal. The question asks for the most efficient way and this should be it (that it matches my preference is just a coincidence).You asked for a recursive version
var inArray = function(arr, needle, index) {
index = index || 0;
if (index >= arr.length)
return false;
return arr[index] === needle
? true
: inArray(arr, needle, index + 1);
}
console.log(inArray([1,5,9], 9));
for...inon an Array? Awsome!? Positively revolting code IMHO