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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With