Check variable equality against a list of values
JavascriptJavascript Problem Overview
I'm checking a variable, say foo
, for equality to a number of values. For example,
if( foo == 1 || foo == 3 || foo == 12 ) {
// ...
}
The point is that it is rather much code for such a trivial task. I came up with the following:
if( foo in {1: 1, 3: 1, 12: 1} ) {
// ...
}
but also this does not completely appeal to me, because I have to give redundant values to the items in the object.
Does anyone know a decent way of doing an equality check against multiple values?
Javascript Solutions
Solution 1 - Javascript
You could use an array and indexOf
:
if ([1,3,12].indexOf(foo) > -1)
Solution 2 - Javascript
In ECMA2016 you can use the includes method. It's the cleanest way I've seen. (Supported by all major browsers)
if([1,3,12].includes(foo)) {
// ...
}
Solution 3 - Javascript
Using the answers provided, I ended up with the following:
Object.prototype.in = function() {
for(var i=0; i<arguments.length; i++)
if(arguments[i] == this) return true;
return false;
}
It can be called like:
if(foo.in(1, 3, 12)) {
// ...
}
Edit: I came across this 'trick' lately which is useful if the values are strings and do not contain special characters. For special characters is becomes ugly due to escaping and is also more error-prone due to that.
/foo|bar|something/.test(str);
To be more precise, this will check the exact string, but then again is more complicated for a simple equality test:
/^(foo|bar|something)$/.test(str);
Solution 4 - Javascript
Now you may have a better solution to resolve this scenario, but other way which i preferred.
const arr = [1,3,12]
if( arr.includes(foo)) { // it will return true if you `foo` is one of array values else false
// code here
}
I preferred above solution over the indexOf check where you need to check index as well.
if ( arr.indexOf( foo ) !== -1 ) { }
Solution 5 - Javascript
This is easily extendable and readable:
switch (foo) {
case 1:
case 3:
case 12:
// ...
break
case 4:
case 5:
case 6:
// something else
break
}
But not necessarily easier :)
Solution 6 - Javascript
You can write if(foo in L(10,20,30))
if you define L
to be
var L = function()
{
var obj = {};
for(var i=0; i<arguments.length; i++)
obj[arguments[i]] = null;
return obj;
};
Solution 7 - Javascript
var a = [1,2,3];
if ( a.indexOf( 1 ) !== -1 ) { }
Note that indexOf is not in the core ECMAScript. You'll need to have a snippet for IE and possibly other browsers that dont support Array.prototype.indexOf.
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)
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;
};
}
Solution 8 - Javascript
Also, since the values against which you're checking the result are all unique you can use the Set.prototype.has() as well.
var valid = [1, 3, 12];
var goodFoo = 3;
var badFoo = 55;
// Test
console.log( new Set(valid).has(goodFoo) );
console.log( new Set(valid).has(badFoo) );
Solution 9 - Javascript
I liked the accepted answer, but thought it would be neat to enable it to take arrays as well, so I expanded it to this:
Object.prototype.isin = function() {
for(var i = arguments.length; i--;) {
var a = arguments[i];
if(a.constructor === Array) {
for(var j = a.length; j--;)
if(a[j] == this) return true;
}
else if(a == this) return true;
}
return false;
}
var lucky = 7,
more = [7, 11, 42];
lucky.isin(2, 3, 5, 8, more) //true
You can remove type coercion by changing ==
to ===
.
Solution 10 - Javascript
If you have access to Underscore, you can use the following:
if (_.contains([1, 3, 12], foo)) {
// ...
}
contains
used to work in Lodash as well (prior to V4), now you have to use includes
if (_.includes([1, 3, 12], foo)) {
handleYellowFruit();
}
Solution 11 - Javascript
For a larger list of values that you compare with often, it is likely more optimal to first construct a Set
and use Set#has
for a constant time check rather than Array#includes
which runs in linear time.
const values = new Set([1, 2, 12]);
if(values.has(foo)){
// do something
}
Solution 12 - Javascript
I simply used jQuery inArray function and an array of values to accomplish this:
myArr = ["A", "B", "C", "C-"];
var test = $.inArray("C", myArr)
// returns index of 2 returns -1 if not in array
if(test >= 0) // true
Solution 13 - Javascript
This is a little helper arrow function:
const letters = ['A', 'B', 'C', 'D'];
function checkInList(arr, val) {
return arr.some(arrVal => val === arrVal);
}
checkInList(letters, 'E'); // false
checkInList(letters, 'A'); // true
Solution 14 - Javascript
Using the ES6 syntax you can do:
Object.prototype.in = function (...args) {
return args.includes(this.valueOf());
}
which incidentally also checks for deep equality. The valueOf() method is needed as this is an object.
Solution 15 - Javascript
For posterity you might want to use regular expressions as an alternative. Pretty good browser support as well (ref. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match#Browser_compatibility)
Try this
if (foo.toString().match(/^(1|3|12)$/)) {
document.write('Regex me IN<br>');
} else {
document.write('Regex me OUT<br>');
}