【问题标题】:What's the prettiest way to compare one value against multiple values? [duplicate]将一个值与多个值进行比较的最漂亮方法是什么? [复制]
【发布时间】:2022-02-01 05:50:18
【问题描述】:

是什么最漂亮的将一个值与多个选项进行比较的方法?

我知道有很多方法可以做到这一点,但我正在寻找最整洁的方法。

我问是因为我希望这是可行的(当你看它时,它不是很明显):

if (foobar == (foo||bar) ) {
     //do something
}
  • 你可以使用像if(/foo|bar|ow|my|javascript|works/.test( foobar )) { /*do something*/ }这样的javascript测试功能这个问题simular to mine
  • 我会在这里注意到 foo 不会正确评估,它不会检查 bar 例如1 === (2 || 1) 将返回错误...
  • 有点旧的线程,但在 ES6 中: if ([foo,bar].includes(foobar) { //do something } 会做

标签: javascript comparison


【解决方案1】:

不要试图太偷偷摸摸,尤其是当它不必要地影响性能时。 如果你真的有一大堆比较要做,那就好好格式化它。

if (foobar === foo ||
    foobar === bar ||
    foobar === baz ||
    foobar === pew) {
     //do something
}

【讨论】:

  • 如果您以递减的概率对术语进行排序以使其为真,则可以加快速度。 :)
  • 在我的世界里,可读性 === 漂亮。这是最易读的。
  • 如果您要比较的项目在您编写代码时是已知的,则此方法有效,但可能不适合您要比​​较的项目是可变的情况。
  • 您可以使用 Array.prototype.every(): [foo, bar].every(elem => elem === compatibleValue);
【解决方案2】:

我用来做的是将这些多个值放在一个数组中,例如

var options = [foo, bar];

然后,使用 indexOf()

if(options.indexOf(foobar) > -1){
   //do something
}

为了漂亮:

if([foo, bar].indexOf(foobar) +1){
   //you can't get any more pretty than this :)
}

对于旧版浏览器:
(https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/IndexOf)

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
        "use strict";
        if (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) { // shortcut for verifying if it's NaN
                n = 0;
            } else if (n != 0 && n != Infinity && n != -Infinity) {
                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;
    }
}

【讨论】:

  • indexOf 仅在 IE 中从版本 9 开始提供数组的indexOf,所以我会避免使用它,直到 8 退出市场(不幸的是,还有很长的路要走)。也就是说,MDN 为不支持它的浏览器提供了示例实现代码。
  • Array.indexOf 方法仅在 Javascript 1.6 及更高版本中受支持,因此您需要对旧版浏览器进行后备。
  • 使用 ES6 的新方法是使用 includes: stackoverflow.com/questions/2430000/…
  • @baptx 这应该是第一个答案。更具可读性,就像 Python 在 (bar, baz) 中的 foo 一样。
  • @l33t 哈哈,很好。显然不是,但不会走这么远......我会使用 [a, b, c, ...].includes(val)
【解决方案3】:

由于没有人添加明显的解决方案,但它适用于两次比较,我将提供它:

if (foobar === foo || foobar === bar) {
     //do something
}

而且,如果您有很多值(可能是数百或数千),那么我建议您制作一个 Set,因为这可以生成非常干净和简单的比较代码,并且在运行时速度很快:

// pre-construct the Set
var tSet = new Set(["foo", "bar", "test1", "test2", "test3", ...]);

// test the Set at runtime
if (tSet.has(foobar)) {
    // do something
}

对于 ES6 之前的版本,您可以获得一个 Set polyfill,其中有很多。在other answer 中描述了一个。

【讨论】:

  • Sets 仍然比字符串比较的原生优化慢。让浏览器做优化。试图智取浏览器的人几乎总是最终得到慢得多的代码。
  • @JackGiffin - 你在这里有什么建议?我的答案的第一部分只是最简单的比较,JS 引擎可以根据自己的喜好进行优化。我使用Set 的答案的第二部分针对您有很多值要比较(数百或数千)的情况。我不明白您的建议是什么而不是这些,或者您认为这些建议有什么问题?
  • Set 比普通 Array:if(['foo', 'bar'].includes(value)) 好在哪里?
  • @DIES - Set 使用哈希表查找,而 .includes() 使用线性搜索。当集合中有多个项目时,Set 应该更快地查看项目是否在 Set 中。另外,.add() 用于Set 可以防止重复。
【解决方案4】:

您可以使用开关:

switch (foobar) {
  case foo:
  case bar:
    // do something
}

【讨论】:

    【解决方案5】:

    只是为了好玩,因为这个问答似乎是关于语法微分析,对 André Alçada Padez 的建议进行了微小的修改:

    (当然还要考虑他包含的 IE9 之前的 shim/shiv/polyfill)

    if (~[foo, bar].indexOf(foobar)) {
        // pretty
    }
    

    【讨论】:

    • !!~['foo', 'bar'].indexOf('foo')?
    【解决方案6】:

    为什么不使用如下数组中的indexOf

    if ([foo, bar].indexOf(foobar) !== -1) {
        // do something
    }
    

    只是普通的 Javascript,没有框架或库,但它会 not work on IE < 9

    【讨论】:

    • 已经提到了两次几乎相同的代码 sn-ps。
    • 非常有趣的使用方式。我没有想到这种语法。感谢您以这种聪明的方式分享。
    【解决方案7】:

    (foobar == foo || foobar == bar) 否则,如果您仅基于单个整数、枚举值或字符串对象比较表达式,则可以使用 switch。见The switch Statement。您也可以使用 André Alçada Padez 建议的方法。最终,您选择的内容将取决于您正在做的事情的细节。

    【讨论】:

    • 上面已经提过三遍了。在堆栈溢出时,您应该只发布不在现有问题答案中的解决方案。
    • @JackGiffin - 如果您查看时间戳,在此之前没有发布多个其他答案来显示此解决方案。这里的答案不一定按发布顺序显示。只有我的回答显示这似乎在它之前,而且在它之前只有 3 秒,所以这个作者不会看到。接受的答案甚至出现在这个答案之后。再说一次,我不确定你为什么要抨击人们超过 6 岁的答案。
    • @jfriend00 你是对的!我研究了所有的时间戳,大卫是骗子,不是 JamieSee。 JamieSee 在 david 之前 14 分钟得到了答案,而 David 的答案完全相同,但 david 获得了荣誉,而 JamieSee 没有。让我们支持 JamieSee 更合理的答案。
    • @JackGiffin - 这不仅仅是关于谁先到达那里。一个好的答案除了它是否在某个地方有正确的内容之外还有其他方面,例如它写得有多清楚,解释做得有多好等等...... OP甚至在大卫的回答中表示它是“最清晰”。有时,写另一个不是那么独特的答案是合适的,因为现有的答案都不能很好地呈现和解释事物。在这种情况下,我并不是在暗示任何事情,只是第一并不是唯一的标准。
    • @JackGiffin - 复选标记应该是最佳答案。这是一场比赛,看谁能写出最好的答案。允许多次提交。直接复制而不添加有价值的东西是不受欢迎的,但是试图写一个更好的答案来更好地解释事情或解释一些新的方面不仅是允许的,而且是需要的。再说一次,我并不是在暗示任何关于这个特殊情况的事情,只是笼统地发表评论。
    【解决方案8】:

    switch 方法(如 Guffa 所述)确实非常有效。但是,大多数 linter 中的默认警告设置会提醒您使用 fall-through。这是我使用 switch 的主要原因之一,所以我几乎忽略了这个警告,但你应该知道,使用 switch 语句的 fall-through 功能可能会很棘手。不过,在这种情况下——我会去的。

    【讨论】:

      【解决方案9】:

      我喜欢用数组测试 indexOf 的漂亮形式,但请注意,这不适用于所有浏览器 (because Array.prototype.indexOf is not present in old IExplorers)。

      但是,通过使用带有 $.inArray() 函数的 jQuery 也有类似的方法:

      if ($.inArray(field, ['value1', 'value2', 'value3']) > -1) {
          alert('value ' + field + ' is into the list'); 
      }
      

      它可能会更好,所以你不应该测试 indexOf 是否存在。

      比较时要小心(不要使用== true/false),因为$.inArray返回的是找到值的匹配位置的索引,如果索引为0,当它真正存在时为false数组。

      【讨论】:

      • 请不要使用 jQuery(除非你确实想要缓慢的代码和缓慢的页面加载速度,在这种情况下,我不会停止疯狂)
      猜你喜欢
      • 1970-01-01
      • 2012-02-25
      • 1970-01-01
      相关资源
      最近更新 更多