A hopefully faster bidirectional indexOf
/ lastIndexOf
alternative
2015
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'];
Performance test
//jsbench.me/7el1b8dj80
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.
The array prototype variant
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'];
How is this possible?
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.
//web.archive.org/web/20151019160219///jsperf.com/bidirectionalindexof/2
Summary: in this tutorial, you’ll learn how to check if an array contains a value in JavaScript.
A value in JavaScript can be primitive such as a number or string. Or it can be an object.
This tutorial shows you to check if an array contain a value, being a primtive value or object.
To check if an array contains a primitive value, you can use the array method like array.includes[]
The following example uses the array.includes[]
method to check if the colors
array contains 'red'
:
Code language: JavaScript [javascript]
const colors = ['red', 'green', 'blue']; const result = colors.includes['red']; console.log[result]; // true
If you want to ingore the letter cases when checking, you can:
- First, return a
new array that contains all elements in lowercase using the
map[]
andtoLocaleLowerCase[]
methods. - Then, use the
includes[]
method to check.
The following example illustrates the steps:
Code language: JavaScript [javascript]
const colors = ['Red', 'GREEN', 'Blue']; const result = colors.map[e => e.toLocaleLowerCase[]] .includes['green']; console.log[result]; // true
In this example, the colors
array doesn’t contain 'green'
but 'GREEN'
.
First, the map[]
method makes every element in the colors
array lowercase and returns a new array. Then, the includes[]
method returns true
because the result array contains the element 'green'
.
2] Check if an array contains a number
The following example shows how to use the includes[]
method to check if an array contains a number:
Code language: JavaScript [javascript]
const ratings = [1,2,3,4,5]; let result = ratings.includes[4]; console.log[result]; // true result = ratings.includes[6]; console.log[result]; // false
3] Check if an array contains an object
The following example uses the includes[]
method to check if an array contains an object:
Code language: JavaScript [javascript]
const john = { 'name': 'John Doe', 'email': '' }; const jane = { 'name': 'Jane Doe', 'email': '' }; const list = [john, jane]; let result = list.includes[john]; console.log[result]; // true
In this example, the list.includes[john]
returns true
because the list
array contains the john
object reference.
In practice, instead of searching for a refenrence, you often search for objects by their property values. The following example won’t work:
Code language: JavaScript [javascript]
const list = [{ 'name': 'John Doe', 'email': '' }, { 'name': 'Jane Doe', 'email': '' }]; let result = list.includes[{ 'name': 'John Doe', 'email': '' }]; console.log[result]; // false
In this example, the following object:
{ 'name': 'John Doe', 'email': '' }
Code language: JavaScript [javascript]
…looks like the first element in the list
array. However, the includes[]
method returns false
because the list
doesn’t contain a reference to the searched object.
To check if an array contains an object, you follow these steps:
- First, create a helper function that compares two objects by their properties.
- Second, use the
array.some[]
method to find the searched object by property values.
To compare objects by property values, you use the following helper function:
Code language: JavaScript [javascript]
const isEqual = [first, second] => { return JSON.stringify[first] === JSON.stringify[second]; }
The isEqual[]
function returns true
if the first
and second
objects have the same number of properties with the same values.
And the limitation of the isEqual[]
function is that the order of properties of the compared objects must be the same.
Note that the some library provides the function that allows you compare two objects by their property values.
For example, Lodash has a _.isEqual[] method that allows you to compare objects if they are equal with a better performance than using the JSON.stringify[]
.
The following uses the array.some[]
method to match every element of an array with the searched object:
Code language: JavaScript [javascript]
const result = list.some[e => isEqual[e, { 'name': 'John Doe', 'email': '' }]]; console.log[result]; // true
Put it all together:
Code language: JavaScript [javascript]
const list = [{ 'name': 'John Doe', 'email': '' }, { 'name': 'Jane Doe', 'email': '' }]; const isEqual = [first, second] => { return JSON.stringify[first] === JSON.stringify[second]; } const result = list.some[e => isEqual[e, { 'name': 'John Doe', 'email': '' }]]; console.log[result]; // true
Summary
- For primitive values, use the
array.includes[]
method to check if an array contains a value. - For objects, use the
isEqual[]
helper function to compare objects andarray.some[]
method to check if the array contains the object.
Was this tutorial helpful ?