Reputation: 75404
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 is very closely related to Stack Overflow question Best way to find an item in a JavaScript Array? which addresses finding objects in an array using indexOf
.
Upvotes: 4975
Views: 3676211
Reputation: 17936
There are a couple of methods which makes this easy to achieve (includes
, some
, find
, findIndex
)
const array = [1, 2, 3, 4, 5, 6, 7];
console.log(array.includes(3));
//includes() determines whether an array includes a certain value among its entries
console.log(array.some(x => x === 3));
//some() tests if at least one element in the array passes the test implemented by the provided function
console.log(array.find(x => x === 3) ? true : false);
//find() returns the value of the first element in the provided array that satisfies the provided testing function
console.log(array.findIndex(x => x === 3) > -1);
//findIndex() returns the index of the first element in the array that satisfies the provided testing function, else returning -1.
More about includes, some, find, findIndex
Upvotes: 26
Reputation: 145
return ARRAY.filter(x => x == SEARCH_VALUE).length > 0 ? true : false;
// For Array Object
function checkArrayItem(SEARCH_KEY, SEARCH_VALUE){
return ARRAY.filter(x => x[SEARCH_KEY] == SEARCH_VALUE).length > 0 ? true : false;
}
Upvotes: 0
Reputation: 468
There are several ways to find out. You can use inbuilt Array methods. The most prominently used is Array find method.
const arr1 = [1, 2, 3, 4, 5]
const result = arr1.find(ele => ele === 4)
console.log(result) //4
const result2 = arr1.find(ele => ele === 6)
console.log(result2) //undefined
/*
If the element is present inside the array
then it will return the first element that
satisfies the given condition. Otherwise
undefined will return.
*/
And if your array is sorted, then you can use binary search on the array.
const recursiveBinarySearch = (arr, target, first = 0, last = arr.length - 1) => {
let firstIndex = first;
let lastIndex = last;
if (lastIndex < firstIndex) return -1;
const midIndex = Math.floor((firstIndex + lastIndex) / 2);
if (arr[midIndex] === target) return midIndex;
if (arr[midIndex] < target) return recursiveBinarySearch(arr, target, midIndex + 1, last);
if (arr[midIndex] > target) return recursiveBinarySearch(arr, target, firstIndex, midIndex - 1);
};
console.log(recursiveBinarySearch([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10)); //9
console.log(recursiveBinarySearch([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2)); // 1
console.log(recursiveBinarySearch(['bird', 'cat', 'dog', 'fish'], 'dog')); // 2
Upvotes: 3
Reputation: 100746
Modern browsers have Array#includes
, which does exactly that and is widely supported by everyone except IE:
console.log(['joe', 'jane', 'mary'].includes('jane')); // true
You can also use Array#indexOf
, which is less direct, but doesn't require polyfills for outdated browsers.
console.log(['joe', 'jane', 'mary'].indexOf('jane') >= 0); // true
Many frameworks also offer similar methods:
$.inArray(value, array, [fromIndex])
_.contains(array, value)
(also aliased as _.include
and _.includes
)dojo.indexOf(array, value, [fromIndex, findLast])
array.indexOf(value)
array.indexOf(value)
findValue(array, value)
array.indexOf(value)
Ext.Array.contains(array, value)
_.includes(array, value, [from])
(is _.contains
prior 4.0.0)R.includes(value, array)
Notice that some frameworks implement this as a function, while others add the function to the array prototype.
Upvotes: 5490
Reputation: 191
see lots of results
const array = [1, 2, 3, 4, 2]
console.log(
array.indexOf(2), // 1
array.filter(e => e == 2), // [ 2, 2 ]
array.includes(2), // true
array.find(e => e == 2) // 2
)
// view does not match
console.log(
array.indexOf(12), // -1
array.filter(e => e == 12), // []
array.includes(12), // false
array.find(e => e == 12) // undefined
)
// match
console.log(
array.indexOf(2) != -1, // true
array.filter(e => e == 2).length > 0, // true
array.includes(2), // true
array.find(e => e == 2) != undefined // true
)
Upvotes: 1
Reputation: 683
This is how you can do.
const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // true
console.log(arr.includes(6)); // false
Upvotes: 1
Reputation: 44
Complexity O(n/2)
You can use any library function but I did it using core JavaScript. We search first search the element in the middle if we get return true, else we search the element in array from left to center and right to center in same time . So it will atmost O(n/2) complexity. And it will return true or false, indicate it exist or not.You can return index number instead of Boolean value
let isExist = (arr, element)=> {
let index = -1;
if ((arr.length % 2 != 0) && arr[(arr.length-1)/2]===element) {
index = 1;
return true;
}
for(let i=0; i<Math.ceil(arr.length-1/2); i++){
if (arr[i]===element || (arr[arr.length-i]===element)) {
index = i;
break;
}
}
return (index<0)? false : true;
}
let array = ['apple', 'ball', 'cat', 'dog', 'egg']
console.log(isExist(array, 'yellow'));
//Result false because yellow doesn't exist in array
console.log(isExist(array, 'cat'));
//Result true because yellow exist in array
Upvotes: 0
Reputation: 4333
The fastest method in Javascript to find if an array contains a value is this:
function existsInArrayForIgnoreDataType(arr, targetElem) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] == targetElem) return true
}
return false
}
You can find the complete study I did here.
Upvotes: -1
Reputation: 27192
If you're just trying to check whether a value is included in a collection, It would be more appropriate to use a Set
, As Arrays
can have duplicate values whereas Sets
cannot. Also, Replacing array.includes
with set.has
improves the performance from O(n2) to O(n). This will be useful when you have to look up multiple values for the same Set. so if you're just going to look up a single value, there's no benefit to use set.has
, you can just use an array.includes
.
Created a jsbench demo, You can run this to check the performance.
Screenshot of the test execution :
Upvotes: 1
Reputation: 287920
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
It can be polyfilled to make it work on all browsers.
Upvotes: 211
Reputation: 15940
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
Upvotes: 509
Reputation: 16706
A hopefully faster bidirectional indexOf
/ lastIndexOf
alternative
While the new method includes
is very nice, the support is basically zero for now.
It's a long time that I was thinking of a 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 is 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');
As a 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.
https://web.archive.org/web/20151019160219/http://jsperf.com/bidirectionalindexof/2
Upvotes: 20
Reputation: 158
The best default method to check if value exist in array JavaScript is some()
Array.prototype.some()
The some()
method tests whether at least one element in the array passes the test implemented by the provided function. It returns true if, in the array, it finds an element for which the provided function returns true; otherwise it returns false. It doesn't modify the array.
const array = [1, 2, 3, 4, 5];
// checks whether an element is even
const even = (element) => element % 2 === 0;
console.log(array.some(even));
// expected output: true
The some
method is the best one in Browser compatibility
For more documentation Array.prototype.some() - JavaScript | MDN
Also you can use other two method is find()
and includes()
. with those method you can get your result but not the best one.
Array.prototype.find() - JavaScript | MDN
Array.prototype.includes() - JavaScript | MDN
Upvotes: 3
Reputation: 454
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:
{id: "104", name: "admin"}
Then you can find the index of that object in the array and replace the object using the 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:
[{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "customer"},
{id: "105", name: "user"}];
Upvotes: 11
Reputation: 4505
Using RegExp:
console.log(new RegExp('26242').test(['23525', '26242', '25272'].join(''))) // true
Upvotes: 1
Reputation: 3242
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'}]
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.
Upvotes: 3
Reputation: 746
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.
Upvotes: 0
Reputation: 22937
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
Upvotes: 268
Reputation: 863
use Array.prototype.includes
for example:
const fruits = ['coconut', 'banana', 'apple']
const doesFruitsHaveCoconut = fruits.includes('coconut')// true
console.log(doesFruitsHaveCoconut)
maybe read this documentation from MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
Upvotes: 6
Reputation: 2180
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
}
Upvotes: 3
Reputation: 657
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"];
var a = "Mango";
checkArray(a, fruits);
function checkArray(a, fruits) {
// Check if a value exists in the fruits array
if (fruits.indexOf(a) !== -1) {
return document.write("true");
} else {
return document.write("false");
}
}
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"];
alert(fruits.includes("Banana")); // Outputs: true
alert(fruits.includes("Coconut")); // Outputs: false
alert(fruits.includes("Orange")); // Outputs: true
alert(fruits.includes("Cherry")); // Outputs: false
For further reference checkout here
Upvotes: 5
Reputation: 92347
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')}`)
let arr = [1,2,3,4,5,'s6','s7','s8','s9','s10'];
//arr = new Array(1000000).fill(123); arr[500000]=7;
function A(a, val) {
var i = -1;
var n = a.length;
while (i++<n) {
if (a[i] === val) {
return true;
}
}
return false;
}
function B(a, val) {
var i = a.length;
while (i--) {
if (a[i] === val) {
return true;
}
}
return false;
}
function C(a, val) {
for (var i = 0; i < a.length; i++) {
if (a[i] === val) return true;
}
return false;
}
function D(a,val)
{
var len = a.length;
for(var i = 0 ; i < len;i++)
{
if(a[i] === val) return true;
}
return false;
}
function E(a, val){
var n = a.length-1;
var t = n/2;
for (var i = 0; i <= t; i++) {
if (a[i] === val || a[n-i] === val) return true;
}
return false;
}
function F(a,val) {
return a.includes(val);
}
function G(a,val) {
return a.indexOf(val)>=0;
}
function H(a,val) {
return !!~a.indexOf(val);
}
function I(a, val) {
return a.findIndex(x=> x==val)>=0;
}
function J(a,val) {
return a.some(x=> x===val);
}
function K(a, val) {
const s = JSON.stringify(val);
return a.some(x => JSON.stringify(x) === s);
}
function L(a,val) {
return !a.every(x=> x!==val);
}
function M(a, val) {
return !!a.find(x=> x==val);
}
function N(a,val) {
return a.filter(x=>x===val).length > 0;
}
function O(a, val) {
return new Set(a).has(val);
}
log('A',A);
log('B',B);
log('C',C);
log('D',D);
log('E',E);
log('F',F);
log('G',G);
log('H',H);
log('I',I);
log('J',J);
log('K',K);
log('L',L);
log('M',M);
log('N',N);
log('O',O);
This shippet only presents functions used in performance tests - it not perform tests itself!
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
Upvotes: 46
Reputation: 1185
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
})
};
Upvotes: 3
Reputation: 7867
One can use Set that has the method "has()":
function contains(arr, obj) {
var proxy = new Set(arr);
if (proxy.has(obj))
return true;
else
return false;
}
var arr = ['Happy', 'New', 'Year'];
console.log(contains(arr, 'Happy'));
Upvotes: 10
Reputation: 121
function countArray(originalArray) {
var compressed = [];
// make a copy of the input array
var copyArray = originalArray.slice(0);
// first loop goes over every element
for (var i = 0; i < originalArray.length; i++) {
var count = 0;
// loop over every element in the copy and see if it's the same
for (var w = 0; w < copyArray.length; w++) {
if (originalArray[i] == copyArray[w]) {
// increase amount of times duplicate is found
count++;
// sets item to undefined
delete copyArray[w];
}
}
if (count > 0) {
var a = new Object();
a.value = originalArray[i];
a.count = count;
compressed.push(a);
}
}
return compressed;
};
// It should go something like this:
var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");
var newArray = countArray(testArray);
console.log(newArray);
Upvotes: 6
Reputation: 632
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 },
{ x: 2, y: 3 },
{ x: 3, y: 3 },
{ x: 3, y: 4 },
{ x: 4, y: 5 } ];
var count = 0;
var n = numbers.length;
for (var i =0;i<n;i++)
{
if(numbers[i].x==numbers[i].y)
{count+=1;}
}
alert(count);
Upvotes: 6
Reputation: 2496
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
Upvotes: 126
Reputation: 2867
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.
Upvotes: 7
Reputation: 1979
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!
Upvotes: 5
Reputation: 104640
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;
}
Upvotes: 7