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.
Related
This question already has answers here:
Array.prototype.includes vs. Array.prototype.indexOf
(11 answers)
Closed 5 years ago.
We have list of ids i.e.1,2,3.
There is a function which accepts id and returns if passed id is in this list or not:
function isIdInList(id) {
return [1,2,3].includes(id);
}
OR
function isIdInList(id) {
return [1,2,3].indexOf(id) > -1;
}
i.e. isIdInList(1) returns true.
isIdInList(5) returns false.
What is the best solution to this, 1 of above two or any other? (Considering the list is hardcoded & The solution should be compatible for all browsers.)
Array.prototype.includes comes from ES2016 specification. It is not supported very well in all web browsers (especially if they are not up-to-date...), so you should probably use the solution with indexOf for full compatibility.
Of course, if you compile your code with Babel or Traceur, you can use includes but it would be wise to add a polyfill like the one suggested in MDN documentation:
// https://tc39.github.io/ecma262/#sec-array.prototype.includes
if (!Array.prototype.includes) {
Object.defineProperty(Array.prototype, 'includes', {
value: function(searchElement, fromIndex) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If len is 0, return false.
if (len === 0) {
return false;
}
// 4. Let n be ? ToInteger(fromIndex).
// (If fromIndex is undefined, this step produces the value 0.)
var n = fromIndex | 0;
// 5. If n ≥ 0, then
// a. Let k be n.
// 6. Else n < 0,
// a. Let k be len + n.
// b. If k < 0, let k be 0.
var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
function sameValueZero(x, y) {
return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
}
// 7. Repeat, while k < len
while (k < len) {
// a. Let elementK be the result of ? Get(O, ! ToString(k)).
// b. If SameValueZero(searchElement, elementK) is true, return true.
// c. Increase k by 1.
if (sameValueZero(o[k], searchElement)) {
return true;
}
k++;
}
// 8. Return false
return false;
}
});
}
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
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
IE9 array does not support indexOf
My Code:
var arrFruits = ['apple', 'banana', 'carrot', 'dates'];
var position = arrFruits.indexOf( 'carrot' );
position > -1 && arrFruits.splice( position, 1 );
alert( arrFruits );
The above code is displaying the result as apple, banana, dates in Chrome. But it is not working in IE9.
It may be issue of .indexOf not being supported. It basically is supported in IE9 unless some malicious doctype is triggering it to render page in IE7/8 mode. Than Array.indexOf method is not supported.
I suggest using HTML5 doctype for example (<!DOCTYPE html>) to make sure IE9 is rendering correctly.
till IE8 it doesn't have .indexOf method , you can add it like this, if you are using IE9 check for compatibility mode
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;
}
}
What is this line for
position > -1 && arrFruits.splice( position, 1 );
It evaluateto either true or false and then you don't do anything with it.that's probably causing a syntax error in IE, which the more forgiving Javascript engines on chrome and Firefox are ignoring.
Maybe you meant to make an if statement?
if(position > -1) {
arrFruits.splice( position, 1 );
}
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.
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;
}
}