if (obj !== obj) does somethig? - javascript

In this page you can see the following example of how to implement an indexOf for arrays:
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(searchElement /*, fromIndex */)
{
"use strict";
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (len === 0)
return -1;
var n = 0;
if (arguments.length > 0)
{
n = Number(arguments[1]);
if (n !== n) // <-- code of interest
n = 0;
else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0))
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
if (n >= len)
return -1;
var k = n >= 0
? n
: Math.max(len - Math.abs(n), 0);
for (; k < len; k++)
{
if (k in t && t[k] === searchElement)
return k;
}
return -1;
};
}
My question is about the line:
if (n !== n)
in which case would this boolean expression return true?

it's a shortcut for verifying if the number is NaN.
say if you have n = Number("string"); then n !== nwould evaluate to true.
in this case you could've use if(isNaN(n)) instead of if(n !== n).

That is how you check for NaN. They are probably doing this as a precaution because it is possible to over write the global function isNaN.

// most of the time you don't need to try to simulate the specification so exactly-
if(!Array.prototype.indexOf){
Array.prototype.indexOf= function(what, i){
if(i==undefined || isNaN(i)) i= 0;
var L= this.length;
while(i< L){
if(this[i]=== what) return i;
++i;
}
return -1;
}
}

Related

can't pass challenge if code not optimized further

I can't pass this coding challenge: Code Challenge: https://www.codewars.com/kata/550f22f4d758534c1100025a/train/javascript
because my code is TOO SLOW. I'm not sure which part of my code is causing the problem. That's why I need help to optimize it.
function dirReduc(arr){
if (arr.length === 0 || arr.length === 1) return [];
let lengthTracker = arr.length;
for (let i = 0; i < arr.length; i++) {
if (lengthTracker > arr.length) {
lengthTracker = arr.length;
i = 0;
}
switch(arr[i]) {
case "NORTH":
arr[i-1] === "SOUTH"? arr.splice(i-1,2) :
arr[i+1] === "SOUTH"? arr.splice(i,2) : null
break;
case "SOUTH":
arr[i-1] === "NORTH"? arr.splice(i-1,2) :
arr[i+1] === "NORTH"? arr.splice(i,2) : null
break;
case "EAST":
arr[i-1] === "WEST"? arr.splice(i-1,2) :
arr[i+1] === "WEST"? arr.splice(i,2) : null
break;
case "WEST":
arr[i-1] === "EAST"? arr.splice(i-1,2) :
arr[i+1] === "EAST"? arr.splice(i,2) : null
break;
}
i===arr.length-1? i=0:null
}
return arr;
}
Splicing can be expensive. We can form a recurrence that assumes the function has already correctly reduced the next part of the list:
function matches(a, b){
return (a == "NORTH" && b == "SOUTH") ||
(b == "NORTH" && a == "SOUTH") ||
(a == "EAST" && b == "WEST") ||
(b == "EAST" && a == "WEST");
}
function f(A, i=0){
if (i == A.length)
return [];
const rest = f(A, i + 1);
const [head,...tail] = rest;
if (head){
if (matches(A[i], head))
return tail;
else
return [A[i]].concat(rest);
}
return [A[i]];
}
I see several problems with this. First, as I mentioned in the comments, splicing long arrays is costly and makes your algorithm O(n^2). Simple and faster would be to use a read-point and a write-point to copy the elements into itself one cell at a time, just skipping over the annihilations and then use splice once at the end to trim the uncopied cells off the end of the array. This would make it O(n).
Secondly, your code is looking both forward and backward for matches which is both unnecessary and can be confusing. Finally, there's no need for a switch (...) as all of the branches do the same thing.
Here is how I would use your code to accomplish this, changing the things mentioned above and noted in the comments.
function dirReduc(arr){
if (arr.length === 0 || arr.length === 1) return [];
let lengthTracker = 0; // the write-point
for(let i = 0; i < arr.length; i++) { // i is the read-point
if(lengthTracker == 0) {
// if no output, copy readpoint to write-point and advance
arr[lengthTracker++] = arr[i];
} else {
// replaces switch()
if (((arr[lengthTracker-1] === "NORTH") && (arr[i] === "SOUTH"))
|| ((arr[lengthTracker-1] === "SOUTH") && (arr[i] === "NORTH"))
|| ((arr[lengthTracker-1] === "EAST") && (arr[i] === "WEST"))
|| ((arr[lengthTracker-1] === "WEST") && (arr[i] === "EAST"))) {
lengthTracker--; // annihilate by decrementing the writepoint
} else {
// copy readpoint to writepoint and advance
arr[lengthTracker++] = arr[i];
}
}
}
//trim the array to only include what was written
arr.splice(lengthTracker);
return arr;
}

Return the first divisible number from an array

I have a function:
function findDivisibleBy(array, num) {
for (i = 0; i < array.length; i++) {
if (array[i] % num == 0 && array[i] != 0) {
return array[i]
} else {
return ('No valid number found!')
}
}
}
I must return the first number in the array that is divisible by the num paramater, and that number can't be 0. The way i'm doing it is not working.
function findDivisibleBy(array, num) {
for (i = 0; i < array.length; i++) {
if (array[i] % num == 0 && array[i] != 0) {
return array[i]
}
}
return ('No valid number found!')
}
The else part is making your function return if the condition isn't met for the first item in the array.
function findDivisibleBy(array, num) {
for (let n of array) {
if (n % num == 0 && n != 0) {
return n
}
}
return ('No valid number found!')
}
You can try this simple code:
function findDivisibleBy(array, num) {
return array.find(x => x % num === 0 && x !== 0) || 'No valid number found!'
}
Use the find method and check for null before returning value.
const findDivisibleBy = (array, num) =>
array.find((val) => val % num === 0 && val !== 0) ?? "No valid number found!";
const input = [3, 0, 4, 5, 8];
console.log(findDivisibleBy(input, 2));
console.log(findDivisibleBy(input, 9));

jquery check if number is in a list [duplicate]

This question already has answers here:
Determine whether an array contains a value [duplicate]
(18 answers)
How to check if jQuery object exist in array?
(5 answers)
Closed 9 years ago.
I have to check whether a variable is equal to a given number or another. For example I am doing this right now.
if (num == 1 || num == 3 || num == 4 || etc.) {
// Do something
} else if (num == 2 || num == 7 || num == 11 || etc.) {
// Do something
}
I thought there should be an easier way. for example an array of all numbers per if statement.
var array1 = [1,3,4,5,6,8,9,10 etc.]
var array2 = [2,7,11,12,13,14 etc.]
And then see if the number is equal to anything inside one of these arrays. But I don't know how to do it..
The indexOf() method searches the array for the specified item, and returns its position.
var array1 = [1,3,4,5,6,8,9,10];
var a = array1.indexOf(46); //a = -1; if not found
If you need to support environments that don't have .indexOf(), you could implement the MDN fix.
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
"use strict";
if (this === void 0 || this === null) throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (len === 0) return -1;
var n = 0;
if (arguments.length > 0) {
n = Number(arguments[1]);
if (n !== n) // shortcut for verifying if it's NaN
n = 0;
else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
if (n >= len) return -1;
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) return k;
}
return -1;
};
}
Since you're asking for jQuery, there is .inArray(). This returns a -1 if it isn't found, else the index of the matching element.
why dont you do a simple for loop?
for(var i = 0; i < array1.length; i++)
{
if(array[i] == num)
{
// do something
break;
}
}
You might use inArray function (http://api.jquery.com/jQuery.inArray/)
<script>var arr = [ 4, "Pete", 8, "John" ];
var $spans = $("span");
$spans.eq(0).text(jQuery.inArray("John", arr));
$spans.eq(1).text(jQuery.inArray(4, arr));
$spans.eq(2).text(jQuery.inArray("Karl", arr));
$spans.eq(3).text(jQuery.inArray("Pete", arr, 2));
</script>
Output:
"John" found at 3
4 found at 0
"Karl" not found, so -1
"Pete" is in the array, but not at or after index 2, so -1
You can do it without jQuery:
if(array1.indexOf(num1) >= 0)//if -1, then not found
You don't need to use jQuery. This is a built in function called indexOf:
if ( arr.indexOf(item) !== -1 ) {
// item is in array
}

Why check the boolean value of Array.prototype.indexOf?

In Fabric.js you see a lot of places where a code block enclosed in a condition check of format:
if (!Array.prototype.indexOf) {} or
if (!Array.prototype.forEach) {} etc.
Isn't the result always false? Why checking the boolean value of a method?
Thanks.
Those tests pass when the functions aren't defined.
Old browsers don't have those functions. That's why they're testing for their presence.
The MDN gives the same example (classical) of this test used to define a replacement function for array.indexOf (for IE before version 9) :
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
"use strict";
if (this == null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (len === 0) {
return -1;
}
var n = 0;
if (arguments.length > 1) {
n = Number(arguments[1]);
if (n != n) { // shortcut for verifying if it's NaN
n = 0;
} else if (n != 0 && n != Infinity && n != -Infinity) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
}
}
It is checking for the existence of the method. If it doesn't exist, it will be undefined, so it'll be doing !undefined, resulting in true.
I would assume that the code is introducing a shim if it doesn't exist.

Crossbrowser "inArray" function (without jQuery)

I wasn't aware of the bad crossbrowser compatibility of array.indexOf() . But now that I am, I need to find a way to achieve the same thing but without using the previous method.
I tried googling for a while, but found no real convincing answers. For now, I am doing it with loops (but this is slow and I am sure there are better ways)
Side Notes:
I can't use jQuery or any other libraries/frameworks.
It doesn't necessarily need to return the index (a simply true/false
will be ok)
I thought it is not necessary to share my code, since you all know how array-loop check looks like (plus it will lower your IQ)
Here is how inArray is implemented in jQuery:
function inArray(elem, array, i) {
var len;
if ( array ) {
if ( array.indexOf ) {
return array.indexOf.call( array, elem, i );
}
len = array.length;
i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
for ( ; i < len; i++ ) {
// Skip accessing in sparse arrays
if ( i in array && array[ i ] === elem ) {
return i;
}
}
}
return -1;
}
You can not use jQuery but why not use their implementation? :-)
Best regards!
From MDN:
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
"use strict";
if (this == null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (len === 0) {
return -1;
}
var n = 0;
if (arguments.length > 0) {
n = Number(arguments[1]);
if (n != n) { // shortcut for verifying if it's NaN
n = 0;
} else if (n != 0 && n != Infinity && n != -Infinity) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
}
}
This checks if it sees a native implementation, if not implement it.
Notable Quirks:
t.length >>> 0; is an unsigned shift for force this to a positive number
For now, I am doing it with loops (but this is slow and I am sure there are better ways)
No matter what you do, it will at the end of the day involve loops. Unless you invent a O(1) algorithm for searching inside an array. There is nothing wrong with using a loop to find the corresponding element. You could even extend the built-in array object with this method so that you can reuse it.

Categories