What is the most concise and efficient way to find out if a JavaScript array contains a value?
This is the only way I know to do it:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Is there a better and more concise way to accomplish this?
This question is related to
javascript
arrays
algorithm
time-complexity
javascript-objects
Use lodash's some function.
It's concise, accurate and has great cross platform support.
The accepted answer does not even meet the requirements.
Requirements: Recommend most concise and efficient way to find out if a JavaScript array contains an object.
Accepted Answer:
$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1
My recommendation:
_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true
Notes:
$.inArray works fine for determining whether a scalar value exists in an array of scalars...
$.inArray(2, [1,2])
> 1
... but the question clearly asks for an efficient way to determine if an object is contained in an array.
In order to handle both scalars and objects, you could do this:
(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
Just another option
// usage: if ( ['a','b','c','d'].contains('b') ) { ... }
Array.prototype.contains = function(value){
for (var key in this)
if (this[key] === value) return true;
return false;
}
Be careful because overloading javascript array objects with custom methods can disrupt the behavior of other javascripts, causing unexpected behavior.
Simple solution for this requirement is using find()
If you're having array of objects like below,
var users = [{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "admin"},
{id: "105", name: "user"}];
Then you can check whether the object with your value is already present or not
let data = users.find(object => object['id'] === '104');
if data is null then no admin, else it will return the existing object like below.
{id: "104", name: "admin"}
Then you can find the index of that object in the array and replace the object using below code.
let indexToUpdate = users.indexOf(data);
let newObject = {id: "104", name: "customer"};
users[indexToUpdate] = newObject;//your new object
console.log(users);
you will get value like below
[{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "customer"},
{id: "105", name: "user"}];
hope this will help anyone.
In Addition to what others said, if you don't have a reference of the object which you want to search in the array, then you can do something like this.
let array = [1, 2, 3, 4, {"key": "value"}];
array.some((element) => JSON.stringify(element) === JSON.stringify({"key": "value"})) // true
array.some((element) => JSON.stringify(element) === JSON.stringify({})) // true
Array.some returns true if any element matches the given condition and returns false if none of the elements matches the given condition.
You can use findIndex function to check if an array has a specific value.
arrObj.findIndex(obj => obj === comparedValue) !== -1;
Returns true if arrObj contains comparedValue, false otherwise.
Use lodash's some function.
It's concise, accurate and has great cross platform support.
The accepted answer does not even meet the requirements.
Requirements: Recommend most concise and efficient way to find out if a JavaScript array contains an object.
Accepted Answer:
$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1
My recommendation:
_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true
Notes:
$.inArray works fine for determining whether a scalar value exists in an array of scalars...
$.inArray(2, [1,2])
> 1
... but the question clearly asks for an efficient way to determine if an object is contained in an array.
In order to handle both scalars and objects, you could do this:
(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
Array.indexOf(Object)
. Array.includes(Object)
. With ECMA 6 you can use Array.find(FunctionName)
where FunctionName
is a user
defined function to search for the object in the array.
Hope this helps!
Let's say you've defined an array like so:
const array = [1, 2, 3, 4]
Below are three ways of checking whether there is a 3
in there. All of them return either true
or false
.
array.includes(3) // true
// Prefixing the method with '_' to avoid name clashes
Object.defineProperty(Array.prototype, '_includes', { value: function (v) { return this.indexOf(v) !== -1 }})
array._includes(3) // true
const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true
Here's how Prototype does it:
/**
* Array#indexOf(item[, offset = 0]) -> Number
* - item (?): A value that may or may not be in the array.
* - offset (Number): The number of initial items to skip before beginning the
* search.
*
* Returns the position of the first occurrence of `item` within the array — or
* `-1` if `item` doesn't exist in the array.
**/
function indexOf(item, i) {
i || (i = 0);
var length = this.length;
if (i < 0) i = length + i;
for (; i < length; i++)
if (this[i] === item) return i;
return -1;
}
Also see here for how they hook it up.
If you're working with ES6 You can use a set:
function arrayHas( array, element ) {
const s = new Set(array);
return s.has(element)
}
This should be more performant than just about any other method
We use this snippet (works with objects, arrays, strings):
/*
* @function
* @name Object.prototype.inArray
* @description Extend Object prototype within inArray function
*
* @param {mix} needle - Search-able needle
* @param {bool} searchInKey - Search needle in keys?
*
*/
Object.defineProperty(Object.prototype, 'inArray',{
value: function(needle, searchInKey){
var object = this;
if( Object.prototype.toString.call(needle) === '[object Object]' ||
Object.prototype.toString.call(needle) === '[object Array]'){
needle = JSON.stringify(needle);
}
return Object.keys(object).some(function(key){
var value = object[key];
if( Object.prototype.toString.call(value) === '[object Object]' ||
Object.prototype.toString.call(value) === '[object Array]'){
value = JSON.stringify(value);
}
if(searchInKey){
if(value === needle || key === needle){
return true;
}
}else{
if(value === needle){
return true;
}
}
});
},
writable: true,
configurable: true,
enumerable: false
});
Usage:
var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first"); //true
a.inArray("foo"); //false
a.inArray("foo", true); //true - search by keys
a.inArray({three: "third"}); //true
var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one"); //true
b.inArray('foo'); //false
b.inArray({foo: 'val'}) //true
b.inArray("{foo: 'val'}") //false
var c = "String";
c.inArray("S"); //true
c.inArray("s"); //false
c.inArray("2", true); //true
c.inArray("20", true); //false
The top answers assume primitive types but if you want to find out if an array contains an object with some trait, Array.prototype.some() is an elegant solution:
const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]
items.some(item => item.a === '3') // returns true
items.some(item => item.a === '4') // returns false
The nice thing about it is that the iteration is aborted once the element is found so unnecessary iteration cycles are spared.
Also, it fits nicely in an if
statement since it returns a boolean:
if (items.some(item => item.a === '3')) {
// do something
}
* As jamess pointed out in the comment, at the time of this answer, September 2018, Array.prototype.some()
is fully supported: caniuse.com support table
ECMAScript 6 has an elegant proposal on find.
The find method executes the callback function once for each element present in the array until it finds one where callback returns a true value. If such an element is found, find immediately returns the value of that element. Otherwise, find returns undefined. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
Here is the MDN documentation on that.
The find functionality works like this.
function isPrime(element, index, array) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) return false;
}
return (element > 1);
}
console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5
You can use this in ECMAScript 5 and below by defining the function.
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
enumerable: false,
configurable: true,
writable: true,
value: function(predicate) {
if (this == null) {
throw new TypeError('Array.prototype.find called on null or undefined');
}
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var list = Object(this);
var length = list.length >>> 0;
var thisArg = arguments[1];
var value;
for (var i = 0; i < length; i++) {
if (i in list) {
value = list[i];
if (predicate.call(thisArg, value, i, list)) {
return value;
}
}
}
return undefined;
}
});
}
Update from 2019: This answer is from 2008 (11 years old!) and is not relevant for modern JS usage. The promised performance improvement was based on a benchmark done in browsers of that time. It might not be relevant to modern JS execution contexts. If you need an easy solution, look for other answers. If you need the best performance, benchmark for yourself in the relevant execution environments.
As others have said, the iteration through the array is probably the best way, but it has been proven that a decreasing while
loop is the fastest way to iterate in JavaScript. So you may want to rewrite your code as follows:
function contains(a, obj) {
var i = a.length;
while (i--) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Of course, you may as well extend Array prototype:
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
And now you can simply use the following:
alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false
Use:
Array.prototype.contains = function(x){
var retVal = -1;
// x is a primitive type
if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}
// x is a function
else if(typeof x =="function") for(var ix in this){
if((this[ix]+"")==(x+"")) retVal = ix;
}
//x is an object...
else {
var sx=JSON.stringify(x);
for(var ix in this){
if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
}
}
//Return False if -1 else number if numeric otherwise string
return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}
I know it's not the best way to go, but since there is no native IComparable way to interact between objects, I guess this is as close as you can get to compare two entities in an array. Also, extending Array object might not be a wise thing to do, but sometimes it's OK (if you are aware of it and the trade-off).
OK, you can just optimise your code to get the result!
There are many ways to do this which are cleaner and better, but I just wanted to get your pattern and apply to that using JSON.stringify
, just simply do something like this in your case:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (JSON.stringify(a[i]) === JSON.stringify(obj)) {
return true;
}
}
return false;
}
Or this solution:
Array.prototype.includes = function (object) {
return !!+~this.indexOf(object);
};
I recommended to use underscore library because its return the value and its supported for all browsers.
var findValue = _.find(array, function(item) {
return item.id == obj.id;
});
Today 2020.01.07 I perform tests on MacOs HighSierra 10.13.6 on Chrome v78.0.0, Safari v13.0.4 and Firefox v71.0.0 for 15 chosen solutions. Conclusions
JSON
, Set
and surprisingly find
(K,N,O) are slowest on all browsersincludes
(F) is fast only on chromefor
(C,D) and indexOf
(G,H) are quite-fast on all browsers on small and big arrays so probably they are best choice for efficient solutionfor
(C,D,E) gives similar results (~630 ops/sec - but the E on safari and firefox was 10-20% slower than C and D)I perform 2 tests cases: for array with 10 elements, and array with 1 milion elements. In both cases we put searched element in the array middle.
let log = (name,f) => console.log(`${name}: 3-${f(arr,'s10')} 's7'-${f(arr,'s7')} 6-${f(arr,6)} 's3'-${f(arr,'s3')}`)_x000D_
_x000D_
let arr = [1,2,3,4,5,'s6','s7','s8','s9','s10'];_x000D_
//arr = new Array(1000000).fill(123); arr[500000]=7;_x000D_
_x000D_
function A(a, val) {_x000D_
var i = -1;_x000D_
var n = a.length;_x000D_
while (i++<n) {_x000D_
if (a[i] === val) {_x000D_
return true;_x000D_
}_x000D_
}_x000D_
return false;_x000D_
}_x000D_
_x000D_
function B(a, val) {_x000D_
var i = a.length;_x000D_
while (i--) {_x000D_
if (a[i] === val) {_x000D_
return true;_x000D_
}_x000D_
}_x000D_
return false;_x000D_
}_x000D_
_x000D_
function C(a, val) {_x000D_
for (var i = 0; i < a.length; i++) {_x000D_
if (a[i] === val) return true;_x000D_
}_x000D_
return false;_x000D_
}_x000D_
_x000D_
function D(a,val)_x000D_
{_x000D_
var len = a.length;_x000D_
for(var i = 0 ; i < len;i++)_x000D_
{_x000D_
if(a[i] === val) return true;_x000D_
}_x000D_
return false;_x000D_
} _x000D_
_x000D_
function E(a, val){ _x000D_
var n = a.length-1;_x000D_
var t = n/2;_x000D_
for (var i = 0; i <= t; i++) {_x000D_
if (a[i] === val || a[n-i] === val) return true;_x000D_
}_x000D_
return false;_x000D_
}_x000D_
_x000D_
function F(a,val) {_x000D_
return a.includes(val);_x000D_
}_x000D_
_x000D_
function G(a,val) {_x000D_
return a.indexOf(val)>=0;_x000D_
}_x000D_
_x000D_
function H(a,val) {_x000D_
return !!~a.indexOf(val);_x000D_
}_x000D_
_x000D_
function I(a, val) {_x000D_
return a.findIndex(x=> x==val)>=0;_x000D_
}_x000D_
_x000D_
function J(a,val) {_x000D_
return a.some(x=> x===val);_x000D_
}_x000D_
_x000D_
function K(a, val) {_x000D_
const s = JSON.stringify(val);_x000D_
return a.some(x => JSON.stringify(x) === s);_x000D_
}_x000D_
_x000D_
function L(a,val) {_x000D_
return !a.every(x=> x!==val);_x000D_
}_x000D_
_x000D_
function M(a, val) {_x000D_
return !!a.find(x=> x==val);_x000D_
}_x000D_
_x000D_
function N(a,val) {_x000D_
return a.filter(x=>x===val).length > 0;_x000D_
}_x000D_
_x000D_
function O(a, val) {_x000D_
return new Set(a).has(val);_x000D_
}_x000D_
_x000D_
log('A',A);_x000D_
log('B',B);_x000D_
log('C',C);_x000D_
log('D',D);_x000D_
log('E',E);_x000D_
log('F',F);_x000D_
log('G',G);_x000D_
log('H',H);_x000D_
log('I',I);_x000D_
log('J',J);_x000D_
log('K',K);_x000D_
log('L',L);_x000D_
log('M',M);_x000D_
log('N',N);_x000D_
log('O',O);
_x000D_
This shippet only presents functions used in performance tests - it not perform tests itself!
_x000D_
Array small - 10 elements
You can perform tests in your machine HERE
Array big - 1.000.000 elements
You can perform tests in your machine HERE
use Array.prototype.includes
for example:
const fruits = ['coconut', 'banana', 'apple']
const doesFruitsHaveCoconut = fruits.includes('coconut')// true
console.log(doesFruitsHaveCoconut)
_x000D_
maybe read this documentation from MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
Literally:
(using Firefox v3.6, with for-in
caveats as previously noted
(HOWEVER the use below might endorse for-in
for this very purpose! That is, enumerating array elements that ACTUALLY exist via a property index (HOWEVER, in particular, the array length
property is NOT enumerated in the for-in
property list!).).)
(Drag & drop the following complete URI's for immediate mode browser testing.)
function ObjInRA(ra){var has=false; for(i in ra){has=true; break;} return has;}
function check(ra){
return ['There is ',ObjInRA(ra)?'an':'NO',' object in [',ra,'].'].join('')
}
alert([
check([{}]), check([]), check([,2,3]),
check(['']), '\t (a null string)', check([,,,])
].join('\n'));
which displays:
There is an object in [[object Object]].
There is NO object in [].
There is an object in [,2,3].
There is an object in [].
(a null string)
There is NO object in [,,].
Wrinkles: if looking for a "specific" object consider:
JavaScript: alert({}!={}); alert({}!=={});
And thus:
obj = {prop:"value"};
ra1 = [obj];
ra2 = [{prop:"value"}];
alert(ra1[0] == obj);
alert(ra2[0] == obj);
Often ra2
is considered to "contain" obj
as the literal entity {prop:"value"}
.
A very coarse, rudimentary, naive (as in code needs qualification enhancing) solution:
obj={prop:"value"}; ra2=[{prop:"value"}];
alert(
ra2 . toSource() . indexOf( obj.toSource().match(/^.(.*).$/)[1] ) != -1 ?
'found' :
'missing' );
Using idnexOf() it is a good solution, but you should hide embedded implementation indexOf() function which returns -1 with ~ operator:
function include(arr,obj) {
return !!(~arr.indexOf(obj));
}
Array.indexOf(Object)
. Array.includes(Object)
. With ECMA 6 you can use Array.find(FunctionName)
where FunctionName
is a user
defined function to search for the object in the array.
Hope this helps!
If you are using JavaScript 1.6 or later (Firefox 1.5 or later) you can use Array.indexOf. Otherwise, I think you are going to end up with something similar to your original code.
You can use findIndex function to check if an array has a specific value.
arrObj.findIndex(obj => obj === comparedValue) !== -1;
Returns true if arrObj contains comparedValue, false otherwise.
Use indexOf()
You can use the indexOf() method to check whether a given value or element exists in an array or not. The indexOf() method returns the index of the element inside the array if it is found, and returns -1 if it not found. Let's take a look at the following example:
var fruits = ["Apple", "Banana", "Mango", "Orange", "Papaya"];_x000D_
var a = "Mango";_x000D_
checkArray(a, fruits);_x000D_
_x000D_
_x000D_
function checkArray(a, fruits) {_x000D_
// Check if a value exists in the fruits array_x000D_
if (fruits.indexOf(a) !== -1) {_x000D_
return document.write("true");_x000D_
} else {_x000D_
return document.write("false");_x000D_
}_x000D_
}
_x000D_
Use include() Method
ES6 has introduced the includes() method to perform this task very easily. But, this method returns only true or false instead of index number:
var fruits = ["Apple", "Banana", "Mango", "Orange", "Papaya"];_x000D_
alert(fruits.includes("Banana")); // Outputs: true_x000D_
alert(fruits.includes("Coconut")); // Outputs: false_x000D_
alert(fruits.includes("Orange")); // Outputs: true_x000D_
alert(fruits.includes("Cherry")); // Outputs: false
_x000D_
For further reference checkout here
function inArray(elem,array)
{
var len = array.length;
for(var i = 0 ; i < len;i++)
{
if(array[i] == elem){return i;}
}
return -1;
}
Returns array index if found, or -1 if not found
Surprised that this question still doesn't have latest syntax added, adding my 2 cents.
Let's say we have array of Objects arrObj and we want to search obj in it.
Array.prototype.indexOf -> (returns index or -1) is generally used for finding index of element in array. This can also be used for searching object but only works if you are passing reference to same object.
let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];
console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1
console.log([1, 3, 5, 2].indexOf(2)); //3
Array.prototype.includes -> (returns true or false)
console.log(arrObj.includes(obj)); //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false
console.log([1, 3, 5, 2].includes(2)); //true
Array.prototype.find -> (takes callback, returns first value/object that returns true in CB).
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }
console.log([1, 3, 5, 2].find(e => e > 2)); //3
Array.prototype.findIndex -> (takes callback, returns index of first value/object that returns true in CB).
console.log(arrObj.findIndex(e => e.age > 40)); //1
console.log(arrObj.findIndex(e => e.age > 40)); //1
console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1
Since find and findIndex takes a callback, we can be fetch any object(even if we don't have the reference) from array by creatively setting the true condition.
I was working on a project that I needed a functionality like python set
which removes all duplicates values and returns a new list, so I wrote this function maybe useful to someone
function set(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) === -1) {
res.push(arr[i]);
}
}
return res;
}
OK, you can just optimise your code to get the result!
There are many ways to do this which are cleaner and better, but I just wanted to get your pattern and apply to that using JSON.stringify
, just simply do something like this in your case:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (JSON.stringify(a[i]) === JSON.stringify(obj)) {
return true;
}
}
return false;
}
Surprised that this question still doesn't have latest syntax added, adding my 2 cents.
Let's say we have array of Objects arrObj and we want to search obj in it.
Array.prototype.indexOf -> (returns index or -1) is generally used for finding index of element in array. This can also be used for searching object but only works if you are passing reference to same object.
let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];
console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1
console.log([1, 3, 5, 2].indexOf(2)); //3
Array.prototype.includes -> (returns true or false)
console.log(arrObj.includes(obj)); //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false
console.log([1, 3, 5, 2].includes(2)); //true
Array.prototype.find -> (takes callback, returns first value/object that returns true in CB).
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }
console.log([1, 3, 5, 2].find(e => e > 2)); //3
Array.prototype.findIndex -> (takes callback, returns index of first value/object that returns true in CB).
console.log(arrObj.findIndex(e => e.age > 40)); //1
console.log(arrObj.findIndex(e => e.age > 40)); //1
console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1
Since find and findIndex takes a callback, we can be fetch any object(even if we don't have the reference) from array by creatively setting the true condition.
ECMAScript 7 introduces Array.prototype.includes
.
It can be used like this:
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
It also accepts an optional second argument fromIndex
:
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
Unlike indexOf
, which uses Strict Equality Comparison, includes
compares using SameValueZero equality algorithm. That means that you can detect if an array includes a NaN
:
[1, 2, NaN].includes(NaN); // true
Also unlike indexOf
, includes
does not skip missing indices:
new Array(5).includes(undefined); // true
Currently it's still a draft but can be polyfilled to make it work on all browsers.
Similar thing: Finds the first element by a "search lambda":
Array.prototype.find = function(search_lambda) {
return this[this.map(search_lambda).indexOf(true)];
};
Usage:
[1,3,4,5,8,3,5].find(function(item) { return item % 2 == 0 })
=> 4
Same in coffeescript:
Array.prototype.find = (search_lambda) -> @[@map(search_lambda).indexOf(true)]
I use the following:
Array.prototype.contains = function (v) {
return this.indexOf(v) > -1;
}
var a = [ 'foo', 'bar' ];
a.contains('foo'); // true
a.contains('fox'); // false
Literally:
(using Firefox v3.6, with for-in
caveats as previously noted
(HOWEVER the use below might endorse for-in
for this very purpose! That is, enumerating array elements that ACTUALLY exist via a property index (HOWEVER, in particular, the array length
property is NOT enumerated in the for-in
property list!).).)
(Drag & drop the following complete URI's for immediate mode browser testing.)
function ObjInRA(ra){var has=false; for(i in ra){has=true; break;} return has;}
function check(ra){
return ['There is ',ObjInRA(ra)?'an':'NO',' object in [',ra,'].'].join('')
}
alert([
check([{}]), check([]), check([,2,3]),
check(['']), '\t (a null string)', check([,,,])
].join('\n'));
which displays:
There is an object in [[object Object]].
There is NO object in [].
There is an object in [,2,3].
There is an object in [].
(a null string)
There is NO object in [,,].
Wrinkles: if looking for a "specific" object consider:
JavaScript: alert({}!={}); alert({}!=={});
And thus:
obj = {prop:"value"};
ra1 = [obj];
ra2 = [{prop:"value"}];
alert(ra1[0] == obj);
alert(ra2[0] == obj);
Often ra2
is considered to "contain" obj
as the literal entity {prop:"value"}
.
A very coarse, rudimentary, naive (as in code needs qualification enhancing) solution:
obj={prop:"value"}; ra2=[{prop:"value"}];
alert(
ra2 . toSource() . indexOf( obj.toSource().match(/^.(.*).$/)[1] ) != -1 ?
'found' :
'missing' );
Simple solution : ES6 Features "includes" method
let arr = [1, 2, 3, 2, 3, 2, 3, 4];
arr.includes(2) // true
arr.includes(93) // false
Here's a JavaScript 1.6 compatible implementation of Array.indexOf
:
if (!Array.indexOf) {
Array.indexOf = [].indexOf ?
function(arr, obj, from) {
return arr.indexOf(obj, from);
} :
function(arr, obj, from) { // (for IE6)
var l = arr.length,
i = from ? parseInt((1 * from) + (from < 0 ? l : 0), 10) : 0;
i = i < 0 ? 0 : i;
for (; i < l; i++) {
if (i in arr && arr[i] === obj) {
return i;
}
}
return -1;
};
}
If you are using JavaScript 1.6 or later (Firefox 1.5 or later) you can use Array.indexOf. Otherwise, I think you are going to end up with something similar to your original code.
You can also use this trick:
var arrayContains = function(object) {
return (serverList.filter(function(currentObject) {
if (currentObject === object) {
return currentObject
}
else {
return false;
}
}).length > 0) ? true : false
}
One can use Set that has the method "has()":
function contains(arr, obj) {_x000D_
var proxy = new Set(arr);_x000D_
if (proxy.has(obj))_x000D_
return true;_x000D_
else_x000D_
return false;_x000D_
}_x000D_
_x000D_
var arr = ['Happy', 'New', 'Year'];_x000D_
console.log(contains(arr, 'Happy'));
_x000D_
It has one parameter: an array numbers of objects. Each object in the array has two integer properties denoted by x and y. The function must return a count of all such objects in the array that satisfy numbers.x == numbers.y
var numbers = [ { x: 1, y: 1 },_x000D_
{ x: 2, y: 3 },_x000D_
{ x: 3, y: 3 },_x000D_
{ x: 3, y: 4 },_x000D_
{ x: 4, y: 5 } ];_x000D_
var count = 0; _x000D_
var n = numbers.length;_x000D_
for (var i =0;i<n;i++)_x000D_
{_x000D_
if(numbers[i].x==numbers[i].y)_x000D_
{count+=1;}_x000D_
}_x000D_
_x000D_
alert(count);
_x000D_
Here's a JavaScript 1.6 compatible implementation of Array.indexOf
:
if (!Array.indexOf) {
Array.indexOf = [].indexOf ?
function(arr, obj, from) {
return arr.indexOf(obj, from);
} :
function(arr, obj, from) { // (for IE6)
var l = arr.length,
i = from ? parseInt((1 * from) + (from < 0 ? l : 0), 10) : 0;
i = i < 0 ? 0 : i;
for (; i < l; i++) {
if (i in arr && arr[i] === obj) {
return i;
}
}
return -1;
};
}
function countArray(originalArray) {_x000D_
_x000D_
var compressed = [];_x000D_
// make a copy of the input array_x000D_
var copyArray = originalArray.slice(0);_x000D_
_x000D_
// first loop goes over every element_x000D_
for (var i = 0; i < originalArray.length; i++) {_x000D_
_x000D_
var count = 0; _x000D_
// loop over every element in the copy and see if it's the same_x000D_
for (var w = 0; w < copyArray.length; w++) {_x000D_
if (originalArray[i] == copyArray[w]) {_x000D_
// increase amount of times duplicate is found_x000D_
count++;_x000D_
// sets item to undefined_x000D_
delete copyArray[w];_x000D_
}_x000D_
}_x000D_
_x000D_
if (count > 0) {_x000D_
var a = new Object();_x000D_
a.value = originalArray[i];_x000D_
a.count = count;_x000D_
compressed.push(a);_x000D_
}_x000D_
}_x000D_
_x000D_
return compressed;_x000D_
};_x000D_
_x000D_
// It should go something like this:_x000D_
_x000D_
var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");_x000D_
var newArray = countArray(testArray);_x000D_
console.log(newArray);
_x000D_
If you are checking repeatedly for existence of an object in an array you should maybe look into
contains(a, obj)
.I use the following:
Array.prototype.contains = function (v) {
return this.indexOf(v) > -1;
}
var a = [ 'foo', 'bar' ];
a.contains('foo'); // true
a.contains('fox'); // false
function inArray(elem,array)
{
var len = array.length;
for(var i = 0 ; i < len;i++)
{
if(array[i] == elem){return i;}
}
return -1;
}
Returns array index if found, or -1 if not found
I was working on a project that I needed a functionality like python set
which removes all duplicates values and returns a new list, so I wrote this function maybe useful to someone
function set(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) === -1) {
res.push(arr[i]);
}
}
return res;
}
This may be a detailed and easy solution.
//plain array
var arr = ['a', 'b', 'c'];
var check = arr.includes('a');
console.log(check); //returns true
if (check)
{
// value exists in array
//write some codes
}
// array with objects
var arr = [
{x:'a', y:'b'},
{x:'p', y:'q'}
];
// if you want to check if x:'p' exists in arr
var check = arr.filter(function (elm){
if (elm.x == 'p')
{
return elm; // returns length = 1 (object exists in array)
}
});
// or y:'q' exists in arr
var check = arr.filter(function (elm){
if (elm.y == 'q')
{
return elm; // returns length = 1 (object exists in array)
}
});
// if you want to check, if the entire object {x:'p', y:'q'} exists in arr
var check = arr.filter(function (elm){
if (elm.x == 'p' && elm.y == 'q')
{
return elm; // returns length = 1 (object exists in array)
}
});
// in all cases
console.log(check.length); // returns 1
if (check.length > 0)
{
// returns true
// object exists in array
//write some codes
}
function contains(a, obj) {
return a.some(function(element){return element == obj;})
}
Array.prototype.some() was added to the ECMA-262 standard in the 5th edition
While array.indexOf(x)!=-1
is the most concise way to do this (and has been supported by non-Internet Explorer browsers for over decade...), it is not O(1), but rather O(N), which is terrible. If your array will not be changing, you can convert your array to a hashtable, then do table[x]!==undefined
or ===undefined
:
Array.prototype.toTable = function() {
var t = {};
this.forEach(function(x){t[x]=true});
return t;
}
Demo:
var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})
(Unfortunately, while you can create an Array.prototype.contains to "freeze" an array and store a hashtable in this._cache in two lines, this would give wrong results if you chose to edit your array later. JavaScript has insufficient hooks to let you keep this state, unlike Python for example.)
This may be a detailed and easy solution.
//plain array
var arr = ['a', 'b', 'c'];
var check = arr.includes('a');
console.log(check); //returns true
if (check)
{
// value exists in array
//write some codes
}
// array with objects
var arr = [
{x:'a', y:'b'},
{x:'p', y:'q'}
];
// if you want to check if x:'p' exists in arr
var check = arr.filter(function (elm){
if (elm.x == 'p')
{
return elm; // returns length = 1 (object exists in array)
}
});
// or y:'q' exists in arr
var check = arr.filter(function (elm){
if (elm.y == 'q')
{
return elm; // returns length = 1 (object exists in array)
}
});
// if you want to check, if the entire object {x:'p', y:'q'} exists in arr
var check = arr.filter(function (elm){
if (elm.x == 'p' && elm.y == 'q')
{
return elm; // returns length = 1 (object exists in array)
}
});
// in all cases
console.log(check.length); // returns 1
if (check.length > 0)
{
// returns true
// object exists in array
//write some codes
}
Here's how Prototype does it:
/**
* Array#indexOf(item[, offset = 0]) -> Number
* - item (?): A value that may or may not be in the array.
* - offset (Number): The number of initial items to skip before beginning the
* search.
*
* Returns the position of the first occurrence of `item` within the array — or
* `-1` if `item` doesn't exist in the array.
**/
function indexOf(item, i) {
i || (i = 0);
var length = this.length;
if (i < 0) i = length + i;
for (; i < length; i++)
if (this[i] === item) return i;
return -1;
}
Also see here for how they hook it up.
Use includes javascript in-build function, but not work in Internet Explorer
var optval = [];
optval.push('A');
optval.push('B');
optval.push('C');
We can search string A in javascript array as:
optval.includes('A') // =====> return true
Thinking out of the box for a second, if you are making this call many many times, it is vastly more efficient to use an associative array a Map to do lookups using a hash function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
One-liner:
function contains(arr, x) {
return arr.filter(function(elem) { return elem == x }).length > 0;
}
Use:
function isInArray(array, search)
{
return array.indexOf(search) >= 0;
}
// Usage
if(isInArray(my_array, "my_value"))
{
//...
}
Update from 2019: This answer is from 2008 (11 years old!) and is not relevant for modern JS usage. The promised performance improvement was based on a benchmark done in browsers of that time. It might not be relevant to modern JS execution contexts. If you need an easy solution, look for other answers. If you need the best performance, benchmark for yourself in the relevant execution environments.
As others have said, the iteration through the array is probably the best way, but it has been proven that a decreasing while
loop is the fastest way to iterate in JavaScript. So you may want to rewrite your code as follows:
function contains(a, obj) {
var i = a.length;
while (i--) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Of course, you may as well extend Array prototype:
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
And now you can simply use the following:
alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false
Or this solution:
Array.prototype.includes = function (object) {
return !!+~this.indexOf(object);
};
Similar thing: Finds the first element by a "search lambda":
Array.prototype.find = function(search_lambda) {
return this[this.map(search_lambda).indexOf(true)];
};
Usage:
[1,3,4,5,8,3,5].find(function(item) { return item % 2 == 0 })
=> 4
Same in coffeescript:
Array.prototype.find = (search_lambda) -> @[@map(search_lambda).indexOf(true)]
Here's a JavaScript 1.6 compatible implementation of Array.indexOf
:
if (!Array.indexOf) {
Array.indexOf = [].indexOf ?
function(arr, obj, from) {
return arr.indexOf(obj, from);
} :
function(arr, obj, from) { // (for IE6)
var l = arr.length,
i = from ? parseInt((1 * from) + (from < 0 ? l : 0), 10) : 0;
i = i < 0 ? 0 : i;
for (; i < l; i++) {
if (i in arr && arr[i] === obj) {
return i;
}
}
return -1;
};
}
I recommended to use underscore library because its return the value and its supported for all browsers.
var findValue = _.find(array, function(item) {
return item.id == obj.id;
});
While array.indexOf(x)!=-1
is the most concise way to do this (and has been supported by non-Internet Explorer browsers for over decade...), it is not O(1), but rather O(N), which is terrible. If your array will not be changing, you can convert your array to a hashtable, then do table[x]!==undefined
or ===undefined
:
Array.prototype.toTable = function() {
var t = {};
this.forEach(function(x){t[x]=true});
return t;
}
Demo:
var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})
(Unfortunately, while you can create an Array.prototype.contains to "freeze" an array and store a hashtable in this._cache in two lines, this would give wrong results if you chose to edit your array later. JavaScript has insufficient hooks to let you keep this state, unlike Python for example.)
By no means the best, but I was just getting creative and adding to the repertoire.
Object.defineProperty(Array.prototype, 'exists', {
value: function(element, index) {
var index = index || 0
return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
}
})
// Outputs 1
console.log(['one', 'two'].exists('two'));
// Outputs -1
console.log(['one', 'two'].exists('three'));
console.log(['one', 'two', 'three', 'four'].exists('four'));
_x000D_
The top answers assume primitive types but if you want to find out if an array contains an object with some trait, Array.prototype.some() is an elegant solution:
const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]
items.some(item => item.a === '3') // returns true
items.some(item => item.a === '4') // returns false
The nice thing about it is that the iteration is aborted once the element is found so unnecessary iteration cycles are spared.
Also, it fits nicely in an if
statement since it returns a boolean:
if (items.some(item => item.a === '3')) {
// do something
}
* As jamess pointed out in the comment, at the time of this answer, September 2018, Array.prototype.some()
is fully supported: caniuse.com support table
indexOf
maybe, but it's a "JavaScript extension to the ECMA-262 standard; as such it may not be present in other implementations of the standard."
Example:
[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1
AFAICS Microsoft does not offer some kind of alternative to this, but you can add similar functionality to arrays in Internet Explorer (and other browsers that don't support indexOf
) if you want to, as a quick Google search reveals (for example, this one).
Thinking out of the box for a second, if you are making this call many many times, it is vastly more efficient to use an associative array a Map to do lookups using a hash function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
If you're working with ES6 You can use a set:
function arrayHas( array, element ) {
const s = new Set(array);
return s.has(element)
}
This should be more performant than just about any other method
Adding a unique item to a another list
searchResults: [
{
name: 'Hello',
artist: 'Selana',
album: 'Riga',
id: 1,
},
{
name: 'Hello;s',
artist: 'Selana G',
album: 'Riga1',
id: 2,
},
{
name: 'Hello2',
artist: 'Selana',
album: 'Riga11',
id: 3,
}
],
playlistTracks: [
{
name: 'Hello',
artist: 'Mamunuus',
album: 'Riga',
id: 4,
},
{
name: 'Hello;s',
artist: 'Mamunuus G',
album: 'Riga1',
id: 2,
},
{
name: 'Hello2',
artist: 'Mamunuus New',
album: 'Riga11',
id: 3,
}
],
playlistName: "New PlayListTrack",
};
}
// Adding an unique track in the playList
addTrack = track => {
if(playlistTracks.find(savedTrack => savedTrack.id === track.id)) {
return;
}
playlistTracks.push(track);
this.setState({
playlistTracks
})
};
Object.keys
for getting all property names of the object and filter all values that exact or partial match with specified string.
function filterByValue(array, string) {
return array.filter(o =>
Object.keys(o).some(k => o[k].toLowerCase().includes(string.toLowerCase())));
}
const arrayOfObject = [{
name: 'Paul',
country: 'Canada',
}, {
name: 'Lea',
country: 'Italy',
}, {
name: 'John',
country: 'Italy'
}];
console.log(filterByValue(arrayOfObject, 'lea')); // [{name: 'Lea', country: 'Italy'}]
console.log(filterByValue(arrayOfObject, 'ita')); // [{name: 'Lea', country: 'Italy'}, {name: 'John', country: 'Italy'}]
_x000D_
You can also filter by specific key such as.
Object.keys(o).some(k => o.country.toLowerCase().includes(string.toLowerCase())));
Now you can just check array count after filtered to check value contains or not.
Hope it's helpful.
I looked through submitted answers and got that they only apply if you search for the object via reference. A simple linear search with reference object comparison.
But lets say you don't have the reference to an object, how will you find the correct object in the array? You will have to go linearly and deep compare with each object. Imagine if the list is too large, and the objects in it are very big containing big pieces of text. The performance drops drastically with the number and size of the elements in the array.
You can stringify objects and put them in the native hash table, but then you will have data redundancy remembering these keys cause JavaScript keeps them for 'for i in obj', and you only want to check if the object exists or not, that is, you have the key.
I thought about this for some time constructing a JSON Schema validator, and I devised a simple wrapper for the native hash table, similar to the sole hash table implementation, with some optimization exceptions which I left to the native hash table to deal with. It only needs performance benchmarking... All the details and code can be found on my blog: http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/ I will soon post benchmark results.
The complete solution works like this:
var a = {'a':1,
'b':{'c':[1,2,[3,45],4,5],
'd':{'q':1, 'b':{'q':1, 'b':8},'c':4},
'u':'lol'},
'e':2};
var b = {'a':1,
'b':{'c':[2,3,[1]],
'd':{'q':3,'b':{'b':3}}},
'e':2};
var c = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
var hc = new HashCache([{a:3, b:2, c:5}, {a:15, b:2, c:'foo'}]); //init
hc.put({a:1, b:1});
hc.put({b:1, a:1});
hc.put(true);
hc.put('true');
hc.put(a);
hc.put(c);
hc.put(d);
console.log(hc.exists('true'));
console.log(hc.exists(a));
console.log(hc.exists(c));
console.log(hc.exists({b:1, a:1}));
hc.remove(a);
console.log(hc.exists(c));
A hopefully faster bidirectional indexOf
/ lastIndexOf
alternative
While the new method includes is very nice, the support is basically zero for now.
It's long time that I was thinking of way to replace the slow indexOf/lastIndexOf functions.
A performant way has already been found, looking at the top answers. From those I chose the contains
function posted by @Damir Zekic which should be the fastest one. But it also states that the benchmarks are from 2008 and so are outdated.
I also prefer while
over for
, but for not a specific reason I ended writing the function with a for loop. It could be also done with a while --
.
I was curious if the iteration was much slower if I check both sides of the array while doing it. Apparently no, and so this function is around two times faster than the top voted ones. Obviously it's also faster than the native one. This in a real world environment, where you never know if the value you are searching is at the beginning or at the end of the array.
When you know you just pushed an array with a value, using lastIndexOf remains probably the best solution, but if you have to travel through big arrays and the result could be everywhere, this could be a solid solution to make things faster.
Bidirectional indexOf/lastIndexOf
function bidirectionalIndexOf(a, b, c, d, e){
for(c=a.length,d=c*1; c--; ){
if(a[c]==b) return c; //or this[c]===b
if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
}
return -1
}
//Usage
bidirectionalIndexOf(array,'value');
http://jsperf.com/bidirectionalindexof
As test I created an array with 100k entries.
Three queries: at the beginning, in the middle & at the end of the array.
I hope you also find this interesting and test the performance.
Note: As you can see I slightly modified the contains
function to reflect the indexOf & lastIndexOf output (so basically true
with the index
and false
with -1
). That shouldn't harm it.
Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
for(c=this.length,d=c*1; c--; ){
if(this[c]==b) return c; //or this[c]===b
if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
}
return -1
},writable:false, enumerable:false});
// Usage
array.bidirectionalIndexOf('value');
The function can also be easily modified to return true or false or even the object, string or whatever it is.
And here is the while
variant:
function bidirectionalIndexOf(a, b, c, d){
c=a.length; d=c-1;
while(c--){
if(b===a[c]) return c;
if(b===a[d-c]) return d-c;
}
return c
}
// Usage
bidirectionalIndexOf(array,'value');
I think that the simple calculation to get the reflected index in an array is so simple that it's two times faster than doing an actual loop iteration.
Here is a complex example doing three checks per iteration, but this is only possible with a longer calculation which causes the slowdown of the code.
Use includes javascript in-build function, but not work in Internet Explorer
var optval = [];
optval.push('A');
optval.push('B');
optval.push('C');
We can search string A in javascript array as:
optval.includes('A') // =====> return true
Use:
Array.prototype.contains = function(x){
var retVal = -1;
// x is a primitive type
if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}
// x is a function
else if(typeof x =="function") for(var ix in this){
if((this[ix]+"")==(x+"")) retVal = ix;
}
//x is an object...
else {
var sx=JSON.stringify(x);
for(var ix in this){
if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
}
}
//Return False if -1 else number if numeric otherwise string
return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}
I know it's not the best way to go, but since there is no native IComparable way to interact between objects, I guess this is as close as you can get to compare two entities in an array. Also, extending Array object might not be a wise thing to do, but sometimes it's OK (if you are aware of it and the trade-off).
Use:
function isInArray(array, search)
{
return array.indexOf(search) >= 0;
}
// Usage
if(isInArray(my_array, "my_value"))
{
//...
}
One-liner:
function contains(arr, x) {
return arr.filter(function(elem) { return elem == x }).length > 0;
}
Use:
var myArray = ['yellow', 'orange', 'red'] ;
alert(!!~myArray.indexOf('red')); //true
To know exactly what the tilde
~
do at this point, refer to this question What does a tilde do when it precedes an expression?.
Use indexOf()
You can use the indexOf() method to check whether a given value or element exists in an array or not. The indexOf() method returns the index of the element inside the array if it is found, and returns -1 if it not found. Let's take a look at the following example:
var fruits = ["Apple", "Banana", "Mango", "Orange", "Papaya"];_x000D_
var a = "Mango";_x000D_
checkArray(a, fruits);_x000D_
_x000D_
_x000D_
function checkArray(a, fruits) {_x000D_
// Check if a value exists in the fruits array_x000D_
if (fruits.indexOf(a) !== -1) {_x000D_
return document.write("true");_x000D_
} else {_x000D_
return document.write("false");_x000D_
}_x000D_
}
_x000D_
Use include() Method
ES6 has introduced the includes() method to perform this task very easily. But, this method returns only true or false instead of index number:
var fruits = ["Apple", "Banana", "Mango", "Orange", "Papaya"];_x000D_
alert(fruits.includes("Banana")); // Outputs: true_x000D_
alert(fruits.includes("Coconut")); // Outputs: false_x000D_
alert(fruits.includes("Orange")); // Outputs: true_x000D_
alert(fruits.includes("Cherry")); // Outputs: false
_x000D_
For further reference checkout here
We use this snippet (works with objects, arrays, strings):
/*
* @function
* @name Object.prototype.inArray
* @description Extend Object prototype within inArray function
*
* @param {mix} needle - Search-able needle
* @param {bool} searchInKey - Search needle in keys?
*
*/
Object.defineProperty(Object.prototype, 'inArray',{
value: function(needle, searchInKey){
var object = this;
if( Object.prototype.toString.call(needle) === '[object Object]' ||
Object.prototype.toString.call(needle) === '[object Array]'){
needle = JSON.stringify(needle);
}
return Object.keys(object).some(function(key){
var value = object[key];
if( Object.prototype.toString.call(value) === '[object Object]' ||
Object.prototype.toString.call(value) === '[object Array]'){
value = JSON.stringify(value);
}
if(searchInKey){
if(value === needle || key === needle){
return true;
}
}else{
if(value === needle){
return true;
}
}
});
},
writable: true,
configurable: true,
enumerable: false
});
Usage:
var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first"); //true
a.inArray("foo"); //false
a.inArray("foo", true); //true - search by keys
a.inArray({three: "third"}); //true
var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one"); //true
b.inArray('foo'); //false
b.inArray({foo: 'val'}) //true
b.inArray("{foo: 'val'}") //false
var c = "String";
c.inArray("S"); //true
c.inArray("s"); //false
c.inArray("2", true); //true
c.inArray("20", true); //false
Simple solution for this requirement is using find()
If you're having array of objects like below,
var users = [{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "admin"},
{id: "105", name: "user"}];
Then you can check whether the object with your value is already present or not
let data = users.find(object => object['id'] === '104');
if data is null then no admin, else it will return the existing object like below.
{id: "104", name: "admin"}
Then you can find the index of that object in the array and replace the object using below code.
let indexToUpdate = users.indexOf(data);
let newObject = {id: "104", name: "customer"};
users[indexToUpdate] = newObject;//your new object
console.log(users);
you will get value like below
[{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "customer"},
{id: "105", name: "user"}];
hope this will help anyone.
It has one parameter: an array numbers of objects. Each object in the array has two integer properties denoted by x and y. The function must return a count of all such objects in the array that satisfy numbers.x == numbers.y
var numbers = [ { x: 1, y: 1 },_x000D_
{ x: 2, y: 3 },_x000D_
{ x: 3, y: 3 },_x000D_
{ x: 3, y: 4 },_x000D_
{ x: 4, y: 5 } ];_x000D_
var count = 0; _x000D_
var n = numbers.length;_x000D_
for (var i =0;i<n;i++)_x000D_
{_x000D_
if(numbers[i].x==numbers[i].y)_x000D_
{count+=1;}_x000D_
}_x000D_
_x000D_
alert(count);
_x000D_
function contains(a, obj) {
return a.some(function(element){return element == obj;})
}
Array.prototype.some() was added to the ECMA-262 standard in the 5th edition
A hopefully faster bidirectional indexOf
/ lastIndexOf
alternative
While the new method includes is very nice, the support is basically zero for now.
It's long time that I was thinking of way to replace the slow indexOf/lastIndexOf functions.
A performant way has already been found, looking at the top answers. From those I chose the contains
function posted by @Damir Zekic which should be the fastest one. But it also states that the benchmarks are from 2008 and so are outdated.
I also prefer while
over for
, but for not a specific reason I ended writing the function with a for loop. It could be also done with a while --
.
I was curious if the iteration was much slower if I check both sides of the array while doing it. Apparently no, and so this function is around two times faster than the top voted ones. Obviously it's also faster than the native one. This in a real world environment, where you never know if the value you are searching is at the beginning or at the end of the array.
When you know you just pushed an array with a value, using lastIndexOf remains probably the best solution, but if you have to travel through big arrays and the result could be everywhere, this could be a solid solution to make things faster.
Bidirectional indexOf/lastIndexOf
function bidirectionalIndexOf(a, b, c, d, e){
for(c=a.length,d=c*1; c--; ){
if(a[c]==b) return c; //or this[c]===b
if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
}
return -1
}
//Usage
bidirectionalIndexOf(array,'value');
http://jsperf.com/bidirectionalindexof
As test I created an array with 100k entries.
Three queries: at the beginning, in the middle & at the end of the array.
I hope you also find this interesting and test the performance.
Note: As you can see I slightly modified the contains
function to reflect the indexOf & lastIndexOf output (so basically true
with the index
and false
with -1
). That shouldn't harm it.
Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
for(c=this.length,d=c*1; c--; ){
if(this[c]==b) return c; //or this[c]===b
if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
}
return -1
},writable:false, enumerable:false});
// Usage
array.bidirectionalIndexOf('value');
The function can also be easily modified to return true or false or even the object, string or whatever it is.
And here is the while
variant:
function bidirectionalIndexOf(a, b, c, d){
c=a.length; d=c-1;
while(c--){
if(b===a[c]) return c;
if(b===a[d-c]) return d-c;
}
return c
}
// Usage
bidirectionalIndexOf(array,'value');
I think that the simple calculation to get the reflected index in an array is so simple that it's two times faster than doing an actual loop iteration.
Here is a complex example doing three checks per iteration, but this is only possible with a longer calculation which causes the slowdown of the code.
indexOf
maybe, but it's a "JavaScript extension to the ECMA-262 standard; as such it may not be present in other implementations of the standard."
Example:
[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1
AFAICS Microsoft does not offer some kind of alternative to this, but you can add similar functionality to arrays in Internet Explorer (and other browsers that don't support indexOf
) if you want to, as a quick Google search reveals (for example, this one).
If you are using JavaScript 1.6 or later (Firefox 1.5 or later) you can use Array.indexOf. Otherwise, I think you are going to end up with something similar to your original code.
Update from 2019: This answer is from 2008 (11 years old!) and is not relevant for modern JS usage. The promised performance improvement was based on a benchmark done in browsers of that time. It might not be relevant to modern JS execution contexts. If you need an easy solution, look for other answers. If you need the best performance, benchmark for yourself in the relevant execution environments.
As others have said, the iteration through the array is probably the best way, but it has been proven that a decreasing while
loop is the fastest way to iterate in JavaScript. So you may want to rewrite your code as follows:
function contains(a, obj) {
var i = a.length;
while (i--) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Of course, you may as well extend Array prototype:
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
And now you can simply use the following:
alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false
ECMAScript 6 has an elegant proposal on find.
The find method executes the callback function once for each element present in the array until it finds one where callback returns a true value. If such an element is found, find immediately returns the value of that element. Otherwise, find returns undefined. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
Here is the MDN documentation on that.
The find functionality works like this.
function isPrime(element, index, array) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) return false;
}
return (element > 1);
}
console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5
You can use this in ECMAScript 5 and below by defining the function.
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
enumerable: false,
configurable: true,
writable: true,
value: function(predicate) {
if (this == null) {
throw new TypeError('Array.prototype.find called on null or undefined');
}
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var list = Object(this);
var length = list.length >>> 0;
var thisArg = arguments[1];
var value;
for (var i = 0; i < length; i++) {
if (i in list) {
value = list[i];
if (predicate.call(thisArg, value, i, list)) {
return value;
}
}
}
return undefined;
}
});
}
Use:
var myArray = ['yellow', 'orange', 'red'] ;
alert(!!~myArray.indexOf('red')); //true
To know exactly what the tilde
~
do at this point, refer to this question What does a tilde do when it precedes an expression?.
Just another option
// usage: if ( ['a','b','c','d'].contains('b') ) { ... }
Array.prototype.contains = function(value){
for (var key in this)
if (this[key] === value) return true;
return false;
}
Be careful because overloading javascript array objects with custom methods can disrupt the behavior of other javascripts, causing unexpected behavior.
One can use Set that has the method "has()":
function contains(arr, obj) {_x000D_
var proxy = new Set(arr);_x000D_
if (proxy.has(obj))_x000D_
return true;_x000D_
else_x000D_
return false;_x000D_
}_x000D_
_x000D_
var arr = ['Happy', 'New', 'Year'];_x000D_
console.log(contains(arr, 'Happy'));
_x000D_
By no means the best, but I was just getting creative and adding to the repertoire.
Object.defineProperty(Array.prototype, 'exists', {
value: function(element, index) {
var index = index || 0
return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
}
})
// Outputs 1
console.log(['one', 'two'].exists('two'));
// Outputs -1
console.log(['one', 'two'].exists('three'));
console.log(['one', 'two', 'three', 'four'].exists('four'));
_x000D_
indexOf
maybe, but it's a "JavaScript extension to the ECMA-262 standard; as such it may not be present in other implementations of the standard."
Example:
[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1
AFAICS Microsoft does not offer some kind of alternative to this, but you can add similar functionality to arrays in Internet Explorer (and other browsers that don't support indexOf
) if you want to, as a quick Google search reveals (for example, this one).
As others have mentioned you can use Array.indexOf
, but it isn't available in all browsers. Here's the code from https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf to make it work the same in older browsers.
indexOf is a recent addition to the ECMA-262 standard; as such it may not be present in all browsers. You can work around this by inserting the following code at the beginning of your scripts, allowing use of indexOf in implementations which do not natively support it. This algorithm is exactly the one specified in ECMA-262, 5th edition, assuming Object, TypeError, Number, Math.floor, Math.abs, and Math.max have their original value.
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;
}
}
use Array.prototype.includes
for example:
const fruits = ['coconut', 'banana', 'apple']
const doesFruitsHaveCoconut = fruits.includes('coconut')// true
console.log(doesFruitsHaveCoconut)
_x000D_
maybe read this documentation from MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
Solution that works in all modern browsers:
function contains(arr, obj) {
const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
return arr.some(item => JSON.stringify(item) === stringifiedObj);
}
Usage:
contains([{a: 1}, {a: 2}], {a: 1}); // true
IE6+ solution:
function contains(arr, obj) {
var stringifiedObj = JSON.stringify(obj)
return arr.some(function (item) {
return JSON.stringify(item) === stringifiedObj;
});
}
// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
Array.prototype.some = function (tester, that /*opt*/) {
for (var i = 0, n = this.length; i < n; i++) {
if (i in this && tester.call(that, this[i], i, this)) return true;
} return false;
};
}
Usage:
contains([{a: 1}, {a: 2}], {a: 1}); // true
JSON.stringify
?Array.indexOf
and Array.includes
(as well as most of the answers here) only compare by reference and not by value.
[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object
Non-optimized ES6 one-liner:
[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true
Note: Comparing objects by value will work better if the keys are in the same order, so to be safe you might sort the keys first with a package like this one: https://www.npmjs.com/package/sort-keys
Updated the contains
function with a perf optimization. Thanks itinance for pointing it out.
I looked through submitted answers and got that they only apply if you search for the object via reference. A simple linear search with reference object comparison.
But lets say you don't have the reference to an object, how will you find the correct object in the array? You will have to go linearly and deep compare with each object. Imagine if the list is too large, and the objects in it are very big containing big pieces of text. The performance drops drastically with the number and size of the elements in the array.
You can stringify objects and put them in the native hash table, but then you will have data redundancy remembering these keys cause JavaScript keeps them for 'for i in obj', and you only want to check if the object exists or not, that is, you have the key.
I thought about this for some time constructing a JSON Schema validator, and I devised a simple wrapper for the native hash table, similar to the sole hash table implementation, with some optimization exceptions which I left to the native hash table to deal with. It only needs performance benchmarking... All the details and code can be found on my blog: http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/ I will soon post benchmark results.
The complete solution works like this:
var a = {'a':1,
'b':{'c':[1,2,[3,45],4,5],
'd':{'q':1, 'b':{'q':1, 'b':8},'c':4},
'u':'lol'},
'e':2};
var b = {'a':1,
'b':{'c':[2,3,[1]],
'd':{'q':3,'b':{'b':3}}},
'e':2};
var c = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
var hc = new HashCache([{a:3, b:2, c:5}, {a:15, b:2, c:'foo'}]); //init
hc.put({a:1, b:1});
hc.put({b:1, a:1});
hc.put(true);
hc.put('true');
hc.put(a);
hc.put(c);
hc.put(d);
console.log(hc.exists('true'));
console.log(hc.exists(a));
console.log(hc.exists(c));
console.log(hc.exists({b:1, a:1}));
hc.remove(a);
console.log(hc.exists(c));
Object.keys
for getting all property names of the object and filter all values that exact or partial match with specified string.
function filterByValue(array, string) {
return array.filter(o =>
Object.keys(o).some(k => o[k].toLowerCase().includes(string.toLowerCase())));
}
const arrayOfObject = [{
name: 'Paul',
country: 'Canada',
}, {
name: 'Lea',
country: 'Italy',
}, {
name: 'John',
country: 'Italy'
}];
console.log(filterByValue(arrayOfObject, 'lea')); // [{name: 'Lea', country: 'Italy'}]
console.log(filterByValue(arrayOfObject, 'ita')); // [{name: 'Lea', country: 'Italy'}, {name: 'John', country: 'Italy'}]
_x000D_
You can also filter by specific key such as.
Object.keys(o).some(k => o.country.toLowerCase().includes(string.toLowerCase())));
Now you can just check array count after filtered to check value contains or not.
Hope it's helpful.
Solution that works in all modern browsers:
function contains(arr, obj) {
const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
return arr.some(item => JSON.stringify(item) === stringifiedObj);
}
Usage:
contains([{a: 1}, {a: 2}], {a: 1}); // true
IE6+ solution:
function contains(arr, obj) {
var stringifiedObj = JSON.stringify(obj)
return arr.some(function (item) {
return JSON.stringify(item) === stringifiedObj;
});
}
// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
Array.prototype.some = function (tester, that /*opt*/) {
for (var i = 0, n = this.length; i < n; i++) {
if (i in this && tester.call(that, this[i], i, this)) return true;
} return false;
};
}
Usage:
contains([{a: 1}, {a: 2}], {a: 1}); // true
JSON.stringify
?Array.indexOf
and Array.includes
(as well as most of the answers here) only compare by reference and not by value.
[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object
Non-optimized ES6 one-liner:
[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true
Note: Comparing objects by value will work better if the keys are in the same order, so to be safe you might sort the keys first with a package like this one: https://www.npmjs.com/package/sort-keys
Updated the contains
function with a perf optimization. Thanks itinance for pointing it out.
function countArray(originalArray) {_x000D_
_x000D_
var compressed = [];_x000D_
// make a copy of the input array_x000D_
var copyArray = originalArray.slice(0);_x000D_
_x000D_
// first loop goes over every element_x000D_
for (var i = 0; i < originalArray.length; i++) {_x000D_
_x000D_
var count = 0; _x000D_
// loop over every element in the copy and see if it's the same_x000D_
for (var w = 0; w < copyArray.length; w++) {_x000D_
if (originalArray[i] == copyArray[w]) {_x000D_
// increase amount of times duplicate is found_x000D_
count++;_x000D_
// sets item to undefined_x000D_
delete copyArray[w];_x000D_
}_x000D_
}_x000D_
_x000D_
if (count > 0) {_x000D_
var a = new Object();_x000D_
a.value = originalArray[i];_x000D_
a.count = count;_x000D_
compressed.push(a);_x000D_
}_x000D_
}_x000D_
_x000D_
return compressed;_x000D_
};_x000D_
_x000D_
// It should go something like this:_x000D_
_x000D_
var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");_x000D_
var newArray = countArray(testArray);_x000D_
console.log(newArray);
_x000D_
In Addition to what others said, if you don't have a reference of the object which you want to search in the array, then you can do something like this.
let array = [1, 2, 3, 4, {"key": "value"}];
array.some((element) => JSON.stringify(element) === JSON.stringify({"key": "value"})) // true
array.some((element) => JSON.stringify(element) === JSON.stringify({})) // true
Array.some returns true if any element matches the given condition and returns false if none of the elements matches the given condition.
Simple solution : ES6 Features "includes" method
let arr = [1, 2, 3, 2, 3, 2, 3, 4];
arr.includes(2) // true
arr.includes(93) // false
Today 2020.01.07 I perform tests on MacOs HighSierra 10.13.6 on Chrome v78.0.0, Safari v13.0.4 and Firefox v71.0.0 for 15 chosen solutions. Conclusions
JSON
, Set
and surprisingly find
(K,N,O) are slowest on all browsersincludes
(F) is fast only on chromefor
(C,D) and indexOf
(G,H) are quite-fast on all browsers on small and big arrays so probably they are best choice for efficient solutionfor
(C,D,E) gives similar results (~630 ops/sec - but the E on safari and firefox was 10-20% slower than C and D)I perform 2 tests cases: for array with 10 elements, and array with 1 milion elements. In both cases we put searched element in the array middle.
let log = (name,f) => console.log(`${name}: 3-${f(arr,'s10')} 's7'-${f(arr,'s7')} 6-${f(arr,6)} 's3'-${f(arr,'s3')}`)_x000D_
_x000D_
let arr = [1,2,3,4,5,'s6','s7','s8','s9','s10'];_x000D_
//arr = new Array(1000000).fill(123); arr[500000]=7;_x000D_
_x000D_
function A(a, val) {_x000D_
var i = -1;_x000D_
var n = a.length;_x000D_
while (i++<n) {_x000D_
if (a[i] === val) {_x000D_
return true;_x000D_
}_x000D_
}_x000D_
return false;_x000D_
}_x000D_
_x000D_
function B(a, val) {_x000D_
var i = a.length;_x000D_
while (i--) {_x000D_
if (a[i] === val) {_x000D_
return true;_x000D_
}_x000D_
}_x000D_
return false;_x000D_
}_x000D_
_x000D_
function C(a, val) {_x000D_
for (var i = 0; i < a.length; i++) {_x000D_
if (a[i] === val) return true;_x000D_
}_x000D_
return false;_x000D_
}_x000D_
_x000D_
function D(a,val)_x000D_
{_x000D_
var len = a.length;_x000D_
for(var i = 0 ; i < len;i++)_x000D_
{_x000D_
if(a[i] === val) return true;_x000D_
}_x000D_
return false;_x000D_
} _x000D_
_x000D_
function E(a, val){ _x000D_
var n = a.length-1;_x000D_
var t = n/2;_x000D_
for (var i = 0; i <= t; i++) {_x000D_
if (a[i] === val || a[n-i] === val) return true;_x000D_
}_x000D_
return false;_x000D_
}_x000D_
_x000D_
function F(a,val) {_x000D_
return a.includes(val);_x000D_
}_x000D_
_x000D_
function G(a,val) {_x000D_
return a.indexOf(val)>=0;_x000D_
}_x000D_
_x000D_
function H(a,val) {_x000D_
return !!~a.indexOf(val);_x000D_
}_x000D_
_x000D_
function I(a, val) {_x000D_
return a.findIndex(x=> x==val)>=0;_x000D_
}_x000D_
_x000D_
function J(a,val) {_x000D_
return a.some(x=> x===val);_x000D_
}_x000D_
_x000D_
function K(a, val) {_x000D_
const s = JSON.stringify(val);_x000D_
return a.some(x => JSON.stringify(x) === s);_x000D_
}_x000D_
_x000D_
function L(a,val) {_x000D_
return !a.every(x=> x!==val);_x000D_
}_x000D_
_x000D_
function M(a, val) {_x000D_
return !!a.find(x=> x==val);_x000D_
}_x000D_
_x000D_
function N(a,val) {_x000D_
return a.filter(x=>x===val).length > 0;_x000D_
}_x000D_
_x000D_
function O(a, val) {_x000D_
return new Set(a).has(val);_x000D_
}_x000D_
_x000D_
log('A',A);_x000D_
log('B',B);_x000D_
log('C',C);_x000D_
log('D',D);_x000D_
log('E',E);_x000D_
log('F',F);_x000D_
log('G',G);_x000D_
log('H',H);_x000D_
log('I',I);_x000D_
log('J',J);_x000D_
log('K',K);_x000D_
log('L',L);_x000D_
log('M',M);_x000D_
log('N',N);_x000D_
log('O',O);
_x000D_
This shippet only presents functions used in performance tests - it not perform tests itself!
_x000D_
Array small - 10 elements
You can perform tests in your machine HERE
Array big - 1.000.000 elements
You can perform tests in your machine HERE
ECMAScript 7 introduces Array.prototype.includes
.
It can be used like this:
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
It also accepts an optional second argument fromIndex
:
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
Unlike indexOf
, which uses Strict Equality Comparison, includes
compares using SameValueZero equality algorithm. That means that you can detect if an array includes a NaN
:
[1, 2, NaN].includes(NaN); // true
Also unlike indexOf
, includes
does not skip missing indices:
new Array(5).includes(undefined); // true
Currently it's still a draft but can be polyfilled to make it work on all browsers.
Update from 2019: This answer is from 2008 (11 years old!) and is not relevant for modern JS usage. The promised performance improvement was based on a benchmark done in browsers of that time. It might not be relevant to modern JS execution contexts. If you need an easy solution, look for other answers. If you need the best performance, benchmark for yourself in the relevant execution environments.
As others have said, the iteration through the array is probably the best way, but it has been proven that a decreasing while
loop is the fastest way to iterate in JavaScript. So you may want to rewrite your code as follows:
function contains(a, obj) {
var i = a.length;
while (i--) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Of course, you may as well extend Array prototype:
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
And now you can simply use the following:
alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false
Let's say you've defined an array like so:
const array = [1, 2, 3, 4]
Below are three ways of checking whether there is a 3
in there. All of them return either true
or false
.
array.includes(3) // true
// Prefixing the method with '_' to avoid name clashes
Object.defineProperty(Array.prototype, '_includes', { value: function (v) { return this.indexOf(v) !== -1 }})
array._includes(3) // true
const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true
indexOf
maybe, but it's a "JavaScript extension to the ECMA-262 standard; as such it may not be present in other implementations of the standard."
Example:
[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1
AFAICS Microsoft does not offer some kind of alternative to this, but you can add similar functionality to arrays in Internet Explorer (and other browsers that don't support indexOf
) if you want to, as a quick Google search reveals (for example, this one).
As others have mentioned you can use Array.indexOf
, but it isn't available in all browsers. Here's the code from https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf to make it work the same in older browsers.
indexOf is a recent addition to the ECMA-262 standard; as such it may not be present in all browsers. You can work around this by inserting the following code at the beginning of your scripts, allowing use of indexOf in implementations which do not natively support it. This algorithm is exactly the one specified in ECMA-262, 5th edition, assuming Object, TypeError, Number, Math.floor, Math.abs, and Math.max have their original value.
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;
}
}
If you are using JavaScript 1.6 or later (Firefox 1.5 or later) you can use Array.indexOf. Otherwise, I think you are going to end up with something similar to your original code.
Using idnexOf() it is a good solution, but you should hide embedded implementation indexOf() function which returns -1 with ~ operator:
function include(arr,obj) {
return !!(~arr.indexOf(obj));
}
Extending the JavaScript Array
object is a really bad idea because you introduce new properties (your custom methods) into for-in
loops which can break existing scripts. A few years ago the authors of the Prototype library had to re-engineer their library implementation to remove just this kind of thing.
If you don't need to worry about compatibility with other JavaScript running on your page, go for it, otherwise, I'd recommend the more awkward, but safer free-standing function solution.
Here's a JavaScript 1.6 compatible implementation of Array.indexOf
:
if (!Array.indexOf) {
Array.indexOf = [].indexOf ?
function(arr, obj, from) {
return arr.indexOf(obj, from);
} :
function(arr, obj, from) { // (for IE6)
var l = arr.length,
i = from ? parseInt((1 * from) + (from < 0 ? l : 0), 10) : 0;
i = i < 0 ? 0 : i;
for (; i < l; i++) {
if (i in arr && arr[i] === obj) {
return i;
}
}
return -1;
};
}
Adding a unique item to a another list
searchResults: [
{
name: 'Hello',
artist: 'Selana',
album: 'Riga',
id: 1,
},
{
name: 'Hello;s',
artist: 'Selana G',
album: 'Riga1',
id: 2,
},
{
name: 'Hello2',
artist: 'Selana',
album: 'Riga11',
id: 3,
}
],
playlistTracks: [
{
name: 'Hello',
artist: 'Mamunuus',
album: 'Riga',
id: 4,
},
{
name: 'Hello;s',
artist: 'Mamunuus G',
album: 'Riga1',
id: 2,
},
{
name: 'Hello2',
artist: 'Mamunuus New',
album: 'Riga11',
id: 3,
}
],
playlistName: "New PlayListTrack",
};
}
// Adding an unique track in the playList
addTrack = track => {
if(playlistTracks.find(savedTrack => savedTrack.id === track.id)) {
return;
}
playlistTracks.push(track);
this.setState({
playlistTracks
})
};
Extending the JavaScript Array
object is a really bad idea because you introduce new properties (your custom methods) into for-in
loops which can break existing scripts. A few years ago the authors of the Prototype library had to re-engineer their library implementation to remove just this kind of thing.
If you don't need to worry about compatibility with other JavaScript running on your page, go for it, otherwise, I'd recommend the more awkward, but safer free-standing function solution.
If you are checking repeatedly for existence of an object in an array you should maybe look into
contains(a, obj)
.You can also use this trick:
var arrayContains = function(object) {
return (serverList.filter(function(currentObject) {
if (currentObject === object) {
return currentObject
}
else {
return false;
}
}).length > 0) ? true : false
}
Source: Stackoverflow.com