views:

306

answers:

7

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? I realize one can use the switch function:

var str = 'a'
var flag = false;

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

if (thisthing || thatthing || flag === true) {
   // do something
}

But this is a horrible mess. It's also clunky to do this:

if (thisthing || thatthing || str === 'a' || str === 'b' || str === 'c') {
   // do something
}

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

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

Any ideas?

UPDATE

I didn't think to mention that in this case, I have to use IE as it's for a corporate intranet page. So ['a', 'b', 'c'].indexOf(str) !== -1 won't work.

Note: here's the full version of the indexOf function for browsers that don't support it. And here's my version (since I don't care about list position or traversing in reverse, this should be faster):

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

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
harto
Aha! That seems to be as close as I can get. Thanks. I gave you the answer because you answered first. Though I would be using SLaks' syntax.
Emtucifor
This will fail on older browsers.
epascarello
Oops... mentioning that this doesn't work in IE would have been nice. :)
Emtucifor
@epascarello: Not only in older browsers, it will fail on *any* IE, even in IE8 :(
CMS
ah. IE. yes, I see.
harto
+5  A: 

You can call indexOf:

if (['a', 'b', 'c'].indexOf(str) >= 0) {
    //do something
}
SLaks
The only problem with `Array.prototype.indexOf` is that it will not work on IE, sadly even IE8 lacks this method.
CMS
But you can define it if you want to. See http://soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorer/
Jason Hall
Here are the "real" goods: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/indexOf
Emtucifor
@ImJasonH: The code on that page is really really bad IMHO, for example, the check if `Array.indexOf` exists before overriding `Array.prototype.indexOf` which are *not* the same thing. I would recommend the implementation made by Mozilla available here: https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/IndexOf
CMS
Listen to @CMS, @Emtucifor, the Mozilla implementation is a lot better.
Jason Hall
A: 

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

var list = ['a', 'b', 'c'];
if (list.include(str)) {
  // do stuff
}
pkaeding
A: 
NW Architect
Oh, they weren't variables but were meant as random placeholders for expressions... just an example of how I planned to use the script.
Emtucifor
+2  A: 

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

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")) {
  // ...
}
CMS
Hmmm, thanks for mentioning that, CMS. It just so happens that this is for a corporate intranet and they use... guess what... IE. Since the regular expression method gives me the willies, I'll either have to make a function that loops, or use the object method I suggested in my post (third code block).
Emtucifor
+1  A: 

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
voyager
voyager, is using "in" any faster/slower/better/worse than just attempting to dereference the item as my third code block in my question showed? Also, if you're going to loop through the thing, I figure you may as well check if the element's in the array at that time... just wrap the loop in a function. And for what it's worth `var i=a.length;while (i--) {/*use a[i]*/}` is the fastest loop method (if reverse order is acceptable).
Emtucifor
@Emtucifor: it really depends on what you are doing, and I guess that it might work differently on different javascript engines. If your data would need at any point the use of a dictionary, then it is better to create it this way. I'd think that this will be faster because of implementation details on the engines (the use of hash tables for object) *once the dict object is created*.
voyager
A: 

SLaks' answer was a good start, but not "correct" because it doesn't work in IE. While I didn't mention the need for IE in my initial post, he didn't mention his code doesn't work in IE, either.

I eventually used the indexOf() function, and "rolled my own" for IE:

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