根据值列表检查变量相等性

我正在检查一个变量,比如 foo,看它是否与多个值相等,

if( foo == 1 || foo == 3 || foo == 12 ) {
// ...
}

关键是,对于这样一个微不足道的任务,它需要的代码太多了:

if( foo in {1: 1, 3: 1, 12: 1} ) {
// ...
}

但这并不完全吸引我,因为我必须给对象中的项赋予多余的值。

有没有人知道一种体面的方法来对多重价值进行平等检查?

182431 次浏览

你可以使用一个数组和 indexOf:

if ([1,3,12].indexOf(foo) > -1)
var a = [1,2,3];


if ( a.indexOf( 1 ) !== -1 ) { }

注意 indexOf 不在核心 ECMAScript 中。您需要为 IE 和其他可能不支持 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;
};
}

这是易于扩展和可读的:

switch (foo) {
case 1:
case 3:
case 12:
// ...
break


case 4:
case 5:
case 6:
// something else
break
}

但不一定更容易:)

如果将 L定义为

var L = function()
{
var obj = {};
for(var i=0; i<arguments.length; i++)
obj[arguments[i]] = null;


return obj;
};

根据提供的答案,我得出了以下结论:

Object.prototype.in = function() {
for(var i=0; i<arguments.length; i++)
if(arguments[i] == this) return true;
return false;
}

可以这么说:

if(foo.in(1, 3, 12)) {
// ...
}

编辑: 我最近碰到了这个“技巧”,如果值是字符串且不包含特殊字符,这个技巧很有用。因为特殊字符由于转义而变得难看,并且由于转义而更容易出错。

/foo|bar|something/.test(str);

更准确地说,这将检查确切的字符串,但是对于一个简单的相等性测试来说,这又是更复杂的:

/^(foo|bar|something)$/.test(str);

我喜欢这个已被接受的答案,但是我认为它也可以用数组来表示,所以我把它扩展成这样:

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

可以通过将 ==更改为 ===来消除类型强制。

如果可以访问下划线,可以使用以下内容:

if (_.contains([1, 3, 12], foo)) {
// ...
}

以前在 Lodash 也可以使用 contains(在 v4之前) ,现在你必须使用 includes

if (_.includes([1, 3, 12], foo)) {
handleYellowFruit();
}

在 ECMA2016中,你可以使用 包括方法。这是我见过的最干净的方法。(所有主流浏览器都支持)

if([1,3,12].includes(foo)) {
// ...
}

另外,由于您检查结果所依据的值都是唯一的,因此您也可以使用 Prototype.has ()

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) );

我只是使用了 jQuery InArray函数和一个值数组来实现这一点:

myArr = ["A", "B", "C", "C-"];


var test = $.inArray("C", myArr)
// returns index of 2 returns -1 if not in array


if(test >= 0) // true

对于子孙后代,你可能需要使用正则表达式作为替代

试试这个

if (foo.toString().match(/^(1|3|12)$/)) {
document.write('Regex me IN<br>');
} else {
document.write('Regex me OUT<br>');
}

这是一个小小的辅助箭头函数:

const letters = ['A', 'B', 'C', 'D'];


function checkInList(arr, val) {
return arr.some(arrVal => val === arrVal);
}


checkInList(letters, 'E');   // false
checkInList(letters, 'A');   // true

更多信息..。

现在你可能有一个更好的解决方案来解决这种情况,但其他方式,我更喜欢。

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
}

我更喜欢以上的解决方案,而不是检查的地方,你需要检查索引。

包括文件

if ( arr.indexOf( foo ) !== -1 ) { }

对于经常进行比较的更大的值列表,可能首先构建一个 Set并使用 Set#has进行恒定时间检查比使用线性时间运行的 Array#includes更为理想。

const values = new Set([1, 2, 12]);
if(values.has(foo)){
// do something
}

使用 ES6语法,您可以:

Object.prototype.in = function (...args) {
return args.includes(this.valueOf());
}

它还检查深度相等性,因为 这个是一个对象,所以需要 valueOf ()方法。

它真的可以归结为用例。例如,如果您只关心变量是否具有任何特定值,那么使用 Array.some()将是最好的选择,因为它基本上对任何可迭代类型执行 forEach,并且在条件满足的第一个值时返回 true。这使得它成为找出是否有任何选项满足条件的最快方法之一,这是如何使用它的一个例子。

const anyOfThese = [1, 2, 14];
const doesHave0 = 0;
const doesHave1 = 1;
const doesHave14 = 14;


// checks all
const found0 = anyOfThese.some(singleValue => singleValue === doesHave0));
console.log("found0", found0);
// -> false


// check anyOfThese[0] = (1) returns without checking the rest
const found1 = anyOfThese.some(singleValue => singleValue === doesHave1));
console.log("found1", found1);
// -> true


// checks anyOfThese[0...14] until it finds singleValue === 14
const found14 = anyOfThese.some(singleValue => singleValue === doesHave14));
console.log("found14", found14);
// -> true

但是,如果您将值存储在某个希望跟踪其总结果的集合中,并且只添加集合中尚未包含的项,例如。使用实际的 Set会更好,因为 Set 对于每个唯一值只能有一个条目,并且只需像这样将其添加到集合中。

const mSet = new Set();
mSet.add(2);
mSet.add(5);
mSet.add(2);
console.debug("mSet", mSet); // -> mSet Set {2, 5}

如果你需要知道这个值是否被添加了,你可以像这样简单的比较一下 Set inline 和 add 的大小

const mSet = new Set();
mSet.add(2);
const addedFive = mSet.size < mSet.add(5).size;
console.debug("addedFive", addedFive);  // -> true
const addedTwo = mSet.size < mSet.add(2).size;
console.debug("addedTwo", addedTwo);  // -> false
console.debug("mSet", mSet); // -> Set {2, 5}

<可以是任何逻辑检查,所以你可以说

const mSet = new Set([2]);
mSet.size === mSet.add(2); // -> returns true; didn't add 2
mSet.size !== mSet.add(2); // -> returns false; didn't add 2
mSet.size === mSet.add(5); // -> returns false; added 5
mSet.size !== mSet.add(6); // -> returns true; added 6

或者你也可以使用任何函数,所以你也可以说

const mSet = new Set([2]);
mSet.size === mSet.remove(2); // -> returns false; removed 2
mSet.size === mSet.remove(2); // -> returns true; didn't remove anything

<>操作符使得你更容易弄清楚你在检查什么,但是 ===!==提供了更广泛的可能性,在这种情况下,确切的变化可能并不重要,但是如果有什么事情发生了或者没有发生变化。

只要记住,在编写逻辑时,这些检查会改变您的值,因此 Set 将真正添加或删除检查的值。