Tom
Tom

Reputation: 3442

Finding an item of an array of numbers without using a loop

This is a stupid question, it feels like one. But mental block is bad right now. :(

My problem is I have an array consisting only of numbers. I want to use that array as a lookup, but the number I pass to lookup a number in the array keeps looking to the array in the index of that number, not whether that number exists in the array.

For example:

var a = [2,4,6,8,10],
b = 2;

if(a[b]){ /* if the number 2 exists in the array a, then do something * }

But that looks at the array value in position 2 (6), not whether the value 2 is in the array. And this makes perfect sense, but (mental block) I can't figure out a way to test whether a number exists in an array of numbers... I even made everything strings, but it does type coercion and the problem persists.

Pulling my hair out here. Please help, thanks. :D

Upvotes: 2

Views: 14964

Answers (5)

Mohammad Usman
Mohammad Usman

Reputation: 39322

You can simply use .includes() method of arrays:

let a = [2, 4, 6, 8, 10],
    b = 2;

if(a.includes(b)) {
    // your code goes here...
}

Upvotes: 2

kennebec
kennebec

Reputation: 104780

A simple loop seems called for here, but-

You can do it without a loop, and without extending IE, if you convert the array to a string.

var a = [2,4,6,8,10], n = 2;

if(RegExp('\\b'+n+'\\b').test(a.join(','))){
// n is in a
}

Upvotes: 3

Tomalak
Tomalak

Reputation: 338218

If you want a native look-up, use an object, not an array.

var a = {2:0,4:0,6:0,8:0,10:0},
    b = 2;

if (b in a) alert "yay!";

note that I use your array value as the key. Using 0 as the value is arbitrary, it does not matter what you put as the value when you use the in operator.

Use 1 or true if you want to be able to do

if (a[b]) alert "yay!";

but I'd recommend using in as this is both ideomatic and less error-prone.


EDIT: Regarding your notion that array lookup would be faster than object lookup. Try it.

console.log('begin building test array and object'); 
var x = [], y = {};
for (var i=0; i<1000; i++) {
  var n = Math.floor(Math.random() * 1000);
  x.push( n );
  y[n] = true;
}
console.log('finished building test array and object'); 

var foo = 0;

console.log('begin 1,000,000 array search rounds at ' + new Date());
for (var i=0; i<1000000; i++) {
  if (x.indexOf(i % 1000) > -1) foo++;
}
console.log('finished array search rounds at ' + new Date());


console.log('begin 1,000,000 object search rounds at ' + new Date());
for (var i=0; i<1000000; i++) {
  if ((i % 1000) in y) foo++;
}
console.log('finished object search rounds at ' + new Date());

Upvotes: 3

jAndy
jAndy

Reputation: 236022

If you just want to check whether or not an item is contained by an Array, you can make usage of the nifty bitwise NOT operator along with the .indexOf() method:

if( ~a.indexOf(b) ) {
    // 2 was found, do domething here
}

It's always a good idea to use a shim or library to make sure methods like .indexOf() are available for your Javascript. @SLaks gave you the example for .indexOf() from MDC.

Short explanation why this works:

The bitwise not operator, negates all bits within a byte. That is also true for the positiv/negative bit. Basically it turns the result "-1" into "0". So, if nothing was found we have a falsy value which we want to have at this point. If we match something at the very beginning and get a result of "0" its translated into "-1" which is just fine since its not a falsy value. Any other possible return value is guaranteed a truthy value.

Upvotes: 3

SLaks
SLaks

Reputation: 887453

if (a.indexOf(2) >= 0)

Note that IE < 9 doesn't have indexOf, so you'll needto add it in case it doesn't exist:

if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(searchElement /*, fromIndex */)
  {
    "use strict";

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (len === 0)
      return -1;

    var n = 0;
    if (arguments.length > 0)
    {
      n = Number(arguments[1]);
      if (n !== n) // shortcut for verifying if it's NaN
        n = 0;
      else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0))
        n = (n > 0 || -1) * Math.floor(Math.abs(n));
    }

    if (n >= len)
      return -1;

    var k = n >= 0
          ? n
          : Math.max(len - Math.abs(n), 0);

    for (; k < len; k++)
    {
      if (k in t && t[k] === searchElement)
        return k;
    }
    return -1;
  };
}

Upvotes: 8

Related Questions