Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance of OR operation ( || ) vs inArray()

Suppose that you want to check what input string a user has entered in a form field. Which one would be the fastest way to check this input against a list of possible values?

The following examples use jQuery.

First method: using ||

if (input == "firstValue" || input == "secondValue" || ... ) {
    ...
}

Second method: using inArray()

if ($.inArray(input, array) >= 0) {
    ...
}

Are there any significant differences between these two methods?

like image 608
user1301428 Avatar asked May 07 '12 08:05

user1301428


4 Answers

You don't want the fastest but the most readable way. And that's in_array() (JavaScript: array.indexOf(value) >= 0) for more than 2 or 3 values.

The performance difference is negligible - while a function call and array creation certainly has some overhead, it doesn't matter compared to expensive operations such a file access, database access, network access, etc.. So in the end nobody will notice the difference.

Here's a short benchmark, each with 1 million iterations:

5.4829950332642 - in_array, the array is recreated everytime
2.9785749912262 - in_array, the array is created only once
0.64996600151062 - isset(), the array way created only once and then the values were turned to keys using array_flip()
2.0508298873901 - ||

So, the fastest, yet still very readable way is this. Unless you create $arr only once and use it many times, there is no need for this and you can simply stay with in_array().

$arr = array_flip(array('your', 'list', 'of', 'values'));
if(isset($arr[$value])) ...

In case you did ask for JavaScript (in this case get rid of those $ prefixes!), the best solution is using Array.indexOf():

['a', 'b', 'c'].indexOf(value) >= 0

However, not all browsers already support Array.indexOf(), so you might want to use e.g. the function from Underscore.js:

_.contains(['a', 'b', 'c'], value)

jQuery also has a function for this:

$.inArray(value, ['a', 'b', 'c'])

The fastest way would be with an object and the in operator, but the object definition is less readable than the array definition:

value in {'a':0, 'b':0, 'c':0}

Here's a JSPerf benchmark for the various solutions: http://jsperf.com/inarray-vs-or - but again, the rather big performance difference is negligible in most cases since you are not going to execute the code millions of times in a loop.

like image 98
ThiefMaster Avatar answered Oct 12 '22 22:10

ThiefMaster


The answer is, it depends...

If there are only a few possibilities, use if (a || b || c).

If there are maybe up to 10, use Array.indexOf()

Note that for the two recommendations above, the choice should depend on readability and not really on performance.

If there are (many) more than that, use an Object with the keys equal to the values, then you can use if (myVar in myKeyObj). This should give at worst O(log n) performance.

like image 22
Alnitak Avatar answered Oct 12 '22 22:10

Alnitak


Performance usually isnt much of a problem when doing javascript, and usually are hard questions to answer.

In this sample the key difference between solutions is scaling. The first solution will always do a predetermined amount of compares, the inArray solution scales worse because it will compare more if there are more values.

However i'd still go with inArray, 99.99% chance performance really doesnt matter. You want to keep your code maintainable, that is more important.

like image 33
TJHeuvel Avatar answered Oct 13 '22 00:10

TJHeuvel


In most languages inArray() is implemented like this:

function inArray(needle, haystack) {
  for (i = 0; i < length; i++) {
    if (haystack[index] == needle) {
      return true;
    }
  }

  return false;
}

If you were to unroll that loop, you'd end up doing

if (haystack[0] == needle) {
  return true;
} 
if (haystack[1] == needle) {
  return true;
}
if (haystack[3] == needle) {
  return true;
}
// and so on

which could be condensed to

if (haystack[0] == needle || haystack[2] == needle || … ) {
  return true;
}

without changing what is happening under the hood.


If you repeatedly have to look up stuff like that, I suggest you get to know maps. instead of

var haystack = ['hello', 'world', 'how', 'is', 'life'];
if (inArray("life", haystack)) {
  // …
}

you do

var haystack = {'hello' : true, 'world' : true, 'how' : true, 'is' : true, 'life' : true};
if (haystack["life"]) {
  // …
}

The more elements have to check against, the better the map will perform compared to the array.

like image 31
rodneyrehm Avatar answered Oct 13 '22 00:10

rodneyrehm