Determine if string is in list in JavaScript

In SQL we can see if a string is in a list like so:

Column IN ('a', 'b', 'c')

What's a good way to do this in JavaScript? It's so clunky to do this:

if (expression1 || expression2 || str === 'a' || str === 'b' || str === 'c') {
   // do something
}

And I'm not sure about the performance or clarity of this:

if (expression1 || expression2 || {a:1, b:1, c:1}[str]) {
   // do something
}

Or one could use the switch function:

var str = 'a',
   flag = false;

switch (str) {
   case 'a':
   case 'b':
   case 'c':
      flag = true;
   default:
}

if (expression1 || expression2 || flag) {
   // do something
}

But that is a horrible mess. Any ideas?

In this case, I have to use Internet Explorer 7 as it's for a corporate intranet page. So ['a', 'b', 'c'].indexOf(str) !== -1 won't work natively without some syntax sugar.

Answers:

Answer

You can call indexOf:

if (['a', 'b', 'c'].indexOf(str) >= 0) {
    //do something
}
Answer

EcmaScript 6

If you're using ES6, you can construct an array of the items, and use includes:

['a', 'b', 'c'].includes('b')

This has some inherent benefits over indexOf because it can properly test for the presence of NaN in the list, and can match missing array elements such as the middle one in [1, , 2] to undefined. includes also works on JavaScript typed arrays such as Uint8Array.

If you're concerned about browser support (such as for IE or Edge), you can check Array.includes at CanIUse.Com, and if you want to target a browser or browser version that's missing include, I recommend polyfill.io for polyfilling.

Without An Array

You could add a new isInList property to strings as follows:

if (!String.prototype.isInList) {
   String.prototype.isInList = function() {
      let value = this.valueOf();
      for (let i = 0, l = arguments.length; i < l; i += 1) {
         if (arguments[i] === value) return true;
      }
      return false;
   }
}

Then use it like so:

'fox'.isInList('weasel', 'fox', 'stoat') // true
'fox'.isInList('weasel', 'stoat') // false

You can do the same thing for Number.prototype.

Array.indexOf

If you are using a modern browser, indexOf always works. However, for IE8 and earlier you'll need a polyfill.

If indexOf returns -1, the item is not in the list. Be mindful though, that this method will not properly check for NaN, and while it can match an explicit undefined, it can’t match a missing element to undefined as in the array [1, , 2].

Polyfill for indexOf or includes in IE, or any other browser/version lacking support

If you don't want to use a service like polyfill.io as mentioned above, you can always include in your own source code standards-compliant custom polyfills. For example, Mozilla Developer Network has one for indexOf.

In this situation where I had to make a solution for Internet Explorer 7, I "rolled my own" simpler version of the indexOf() function that is not standards-compliant:

if (!Array.prototype.indexOf) {
   Array.prototype.indexOf = function(item) {
      var i = this.length;
      while (i--) {
         if (this[i] === item) return i;
      }
      return -1;
   }
}

However, I don't think modifying Array.prototype is the best answer in the long term. Modifying Object and Array prototypes in JavaScript can lead to serious bugs. You need to decide whether doing so is safe in your own environment. Of primary note is that iterating an array (when Array.prototype has added properties) with for ... in will return the new function name as one of the keys:

Array.prototype.blah = function() { console.log('blah'); };
let arr = [1, 2, 3];
for (let x in arr) { console.log(x); }
// Result:
0
1
2
blah // Extra member iterated over!

Your code may work now, but the moment someone in the future adds a third-party JavaScript library or plugin that isn't zealously guarding against inherited keys, everything can break.

The old way to avoid that breakage is, during enumeration, to check each value to see if the object actually has it as a non-inherited property with if (arr.hasOwnProperty(x)) and only then work with that x.

The new ES6 way to avoid this extra-key problem is to use of instead of in, for (let x of arr). However, unless you can guarantee that all of your code and third-party libraries strictly stick to this method, then for the purposes of this question you'll probably just want to use includes as stated above.

Answer

Most of the answers suggest the Array.prototype.indexOf method, the only problem is that it will not work on any IE version before IE9.

As an alternative I leave you two more options that will work on all browsers:

if (/Foo|Bar|Baz/.test(str)) {
  // ...
}


if (str.match("Foo|Bar|Baz")) {
  // ...
}
Answer

Arrays have an indexOf method which can be used to search for strings:

js> a = ['foo', 'bar', 'baz']
foo,bar,baz
js> a.indexOf('bar')
1
js> a.indexOf('quux')
-1
Answer

A trick I've used is

>>> ("something" in {"a string":"", "somthing":"", "another string":""})
false
>>> ("something" in {"a string":"", "something":"", "another string":""})
true

You could do something like

>>> a = ["a string", "something", "another string"];
>>> b = {};
>>> for(var i=0; i<a.length;i++){b[a[i]]="";} /* Transform the array in a dict */
>>> ("something" in b)
true
Answer

Here's mine:

String.prototype.inList=function(list){
    return (Array.apply(null, arguments).indexOf(this.toString()) != -1)
}

var x = 'abc';
if (x.inList('aaa','bbb','abc'))
    console.log('yes');
else
    console.log('no');

This one is faster if you're OK with passing an array:

String.prototype.inList=function(list){
    return (list.indexOf(this.toString()) != -1)
}

var x = 'abc';
if (x.inList(['aaa','bbb','abc']))
    console.log('yes')

Here's the jsperf: http://jsperf.com/bmcgin-inlsit

Answer

RegExp is universal, but I understand that you're working with arrays. So, check out this approach. I use to use it, and it's very effective and blazing fast!

var str = 'some string with a';
var list = ['a', 'b', 'c'];
var rx = new RegExp(list.join('|'));

rx.test(str);

You can also apply some modifications, i.e.:

One-liner

new RegExp(list.join('|')).test(str);

Case insensitive

var rx = new RegExp(list.join('|').concat('/i'));


And many others!

Answer

Using indexOf(it doesn’t work with IE8).

if (['apple', 'cherry', 'orange', 'banana'].indexOf(value) >= 0) {
    // found
}

To support IE8, you could implement Mozilla’s indexOf.

if (!Array.prototype.indexOf) {
    // indexOf polyfill code here
}

Regular Expressions via String.prototype.match (docs).

if (fruit.match(/^(banana|lemon|mango|pineapple)$/)) {

}
Answer

Looks like you need to use in_array function.

jQuery -> inArray

Prototype -> Array.indexOf

Or, see these examples if you are not using jQuery or Prototype:

Stylistic note: variables named thisthing thatthing, should be named to tell you something about what they contain (noun).

Answer

In addition to indexOf (which other posters have suggested), using prototype's Enumerable.include() can make this more neat and concise:

var list = ['a', 'b', 'c'];
if (list.include(str)) {
  // do stuff
}
Answer

Thanks for the question, and the solution using the Array.indexOf method.

I used the code from this solution to create a inList() function that would, IMO, make the writing simpler and the reading clearer:

function inList(psString, psList) 
{
    var laList = psList.split(',');

    var i = laList.length;
    while (i--) {
        if (laList[i] === psString) return true;
    }
    return false;
}

USAGE:

if (inList('Houston', 'LA,New York,Houston') {
  // THEN do something when your string is in the list
}
Answer

I'm surprised no one had mentioned a simple function that takes a string and a list.

function in_list(needle, hay)
{
    var i, len;

    for (i = 0, len = hay.length; i < len; i++)
    {
        if (hay[i] == needle) { return true; }
    }

    return false;
}

var alist = ["test"];

console.log(in_list("test", alist));
Answer

My solution results in a syntax like this:

// Checking to see if var 'column' is in array ['a', 'b', 'c']

if (column.isAmong(['a', 'b', 'c']) {
  // Do something
}

And I implement this by extending the basic Object prototype, like this:

Object.prototype.isAmong = function (MyArray){
   for (var a=0; a<MyArray.length; a++) {
      if (this === MyArray[a]) { 
          return true;
      }
   }
   return false;
}

We might alternatively name the method isInArray (but probably not inArray) or simply isIn.

Advantages: Simple, straightforward, and self-documenting.

Answer

r = (['.', 'ArrowLeft', 'ArrowRight',
                      'Delete','Backspace'].filter(k => k === '.').length === 1); 
console.log(r); 

This checks for '.' in list.

Answer

A simplified version of SLaks' answer also works:

if ('abcdefghij'.indexOf(str) >= 0) {
    // Do something
}

....since strings are sort of arrays themselves. :)

If needed, implement the indexof function for Internet Explorer as described before me.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.