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


133

我正在检查一个变量,例如foo,是否等于多个值。例如,

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

关键是,对于这样一个琐碎的任务,这是很多代码。我提出以下内容:

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

但这也不完全吸引我,因为我必须为对象中的项目提供冗余值。

有谁知道对多个值进行相等性检查的体面方法?


我认为在决定这样的事情时需要涉及更大的上下文,因为了解为什么要进行这样的比较很重要。
Pointy

好吧,在我正在创建的游戏中,我正在检查键盘代码,以便确定应调用的功能。在不同的浏览器中,键显然具有不同的键代码,因此需要与多个值进行比较。
pimvdb 2011年

检查多种方法的性能测试,逻辑运算符赢得runkit.com/pramendra/58cad911146c1c00147f8d8d
Pramendra Gupta

Answers:


175

您可以使用数组和indexOf

if ([1,3,12].indexOf(foo) > -1)

1
我喜欢这一个。我猜想甚至可以通过原型创建一个“包含”功能,从而避免使用> -1。
pimvdb 2011年

1
@pimvdb:请注意,您可能需要自己的实现,indexOf只有自ECMAScript 5版以来才可用。
Gumbo

在另一个答案中,确实也提到了这一点,我不知道,谢谢
pimvdb 2011年

'>'在某种程度上比'!=='好吗?
马克斯·沃特曼

116

在ECMA2016中,可以使用include方法。这是我所见过的最干净的方式。(除IE之外,所有主流浏览器均支持(链接中包含“填充”)

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

4
对于变量if([a,b,c].includes(foo))或字符串if(['a','b','c'].includes(foo))
Hastig Zusammenstellen'Mar

对于变量=>,if([a,b,c].includes(foo))因为引号会将其设置为字符串。@HastigZusammenstellen
iambinodstha

2
@BinodShrestha我认为那是我写的,除非我遗漏了一些东西。“对于变量..或字符串...”
Hastig Zusammenstellen

16

使用提供的答案,我得出以下结论:

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

5
天哪!我很惊讶这是有效的- in是Javascript中的关键字。例如,运行function in() {}; in()至少在Firefox中会导致语法错误,但我不确定为什么您的代码没有。:-)
Ben Blank

3
另外,扩展常常被认为是不好的做法Object.prototype,因为它for (foo in bar)以不幸的方式影响。也许将其更改为function contains(obj) { for (var i = 1; i < arguments.length; i++) if (arguments[i] === obj) return true; return false; }并将对象作为参数传递?
本·布兰克

感谢您的回应,在此代码本身可以正常运行的同时,Google Closure编译器在编译时也会返回错误。无论如何,已经有人建议,Object.prototype与您也提到的扩展相比,帮助程序类可以更好地完成此工作。但是,我确实更喜欢这种方式,因为检查的符号很可爱,就像foo.in(1, 2, "test", Infinity)馅饼一样容易。
pimvdb

并且in()在Chrome上以常规方式定义函数也失败了,但是原型
仍然

3
扩展Object.prototype是一种反模式,不应使用。改用一个函数。
弗农

9

你可以写if(foo in L(10,20,30)),如果你定义L

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

    return obj;
};

这实际上比以前的答案更清楚,谢谢!
pimvdb 2011年

2
我认为应该谨慎地说原型函数也位于数组/对象中-因此,如果数组/对象的原型中存在函数“删除”,则即使您未编写代码'remove' in L(1, 3, 12),它也始终返回true。指定“删除”以放入列表中。
pimvdb 2011年

7

这很容易扩展和读取:

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

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

但不一定更容易:)


我实际上使用了此方法,因为我想在每个值旁边添加一个注释以描述与该值相关的内容,这是实现该值的最易读的方法。
pholcroft

@pholcroft如果需要描述每个值所关联的内容,则应创建一个枚举或类,并编写属性以使用描述性名称。
red_dorian

6
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;
  };
}

它是Mozilla的直接副本。太懒了,无法链接。developer.mozilla.org/en/JavaScript/Reference/Global_Objects/...
MEDER omuraliev

如果您实际上不移位,则在定义len时有位移的原因吗?这里有隐性强制吗?
jaredad7'9


2

现在您可能有更好的解决方案来解决此问题,但是我更喜欢其他方式。

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    
}

我更喜欢上面的解决方案,而不是需要检查索引的indexOf check。

包括文件

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

1

我喜欢接受的答案,但认为使它也能够采用数组会很巧妙,因此我将其扩展为:

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

您可以通过更改==为删除类型强制===


1

如果可以访问Underscore,则可以使用以下命令:

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

contains 以前也可以在Lodash中使用(V4之前的版本),现在您必须使用 includes

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

1

这是一个辅助的辅助函数:

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 valToCheck = 'E'; const check = ['A', 'B', 'C', 'D'].some(option => option === valToCheck); // false
Giorgio Tempesta

但是,一旦我开始调整代码,我发现它includes会变成更好的选择,例如@alister的答案:const valToCheck = 'E'; const check = ['A', 'B', 'C', 'D'].includes(valToCheck); // false
Giorgio Tempesta

0

我只是使用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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.