如何检查数组是否包含 JavaScript 中的值?

问题描述:

找出 JavaScript 数组是否包含值的最简洁有效的方法是什么?

这是我知道的唯一方法:

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (a[i] === obj) {
            return true;
        }
    }
    return false;
}

有没有更好更简洁的方法来实现这一点?

这与 Stack Overflow 问题 Best way to find an item in a JavaScript Array? 密切相关,该问题解决了使用 indexOf 在数组中查找对象的问题。

解决方案1:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

现代浏览器具有 Array#includes,它完全做到这一点,并且 is widely supported 被除 IE 之外的所有人:

console.log([‘joe’, ‘jane’, ‘mary’].includes(‘jane’)); //真的

您也可以使用 Array#indexOf,它不太直接,但对于过时的浏览器不需要 polyfill。

console.log([‘joe’, ‘jane’, ‘mary’].indexOf(‘jane’) >= 0); //真的

许多框架也提供了类似的方法:

jQuery: $.inArray(value, array, [fromIndex])

Underscore.js:_.contains(array, value)(也别名为 _.include 和 _.includes)

Dojo 工具包:dojo.indexOf(array, value, [fromIndex, findLast])

原型:array.indexOf(value)

MooTools:array.indexOf(值)

MochiKit:findValue(数组,值)

MS Ajax:array.indexOf(value)

分机:Ext.Array.contains(数组,值)

Lodash: _.includes(array, value, [from]) (是 _.contains 之前的 4.0.0)

Ramda:R.includes(值,数组)

请注意,一些框架将其实现为一个函数,而另一些框架则将该函数添加到数组原型中。

MooTools 也有返回布尔值的 Array.contains,这听起来像是这里的真正问题。

原型还具有返回布尔值的 Array.include

如果您使用的是好的浏览器,您可以使用 array.indexOf(object) != -1

另外,不要单独使用 indexOf 作为条件,因为第一个元素将返回 0 并将被评估为 falsy

inArray 是返回元素索引的函数的糟糕名称,如果不存在则返回 -1。我希望返回一个布尔值。

解决方案2:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

2019 年更新:此答案来自 2008 年(11 岁!),与现代 JS 使用无关。承诺的性能改进是基于当时在浏览器中完成的基准测试。它可能与现代 JS 执行上下文无关。如果您需要一个简单的解决方案,请寻找其他答案。如果您需要最佳性能,请在相关执行环境中为自己进行基准测试。

正如其他人所说,通过数组进行迭代可能是最好的方法,但是 has been proven 递减 while 循环是 JavaScript 中迭代的最快方法。所以你可能想重写你的代码如下:

function contains(a, obj) {
    var i = a.length;
    while (i--) {
       if (a[i] === obj) {
           return true;
       }
    }
    return false;
}

当然,你也可以扩展 Array 原型:

Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}

现在您可以简单地使用以下内容:

alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false

但要小心:stackoverflow.com/questions/237104/javascript-array-containsobj/…

“证明”是一个强有力的词。 JS 引擎不断改进,3 年前测量的执行时间已经过时了。

解决方案3:

huntsbot.com – 高效赚钱,自由工作

indexOf 可能,但它是“ECMA-262 标准的 JavaScript 扩展;因此它可能不存在于该标准的其他实现中。”

例子:

[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1

AFAICS Microsoft does not offer some kind of alternative,但如果您愿意,可以将类似的功能添加到 Internet Explorer(以及不支持 indexOf 的其他浏览器)中的数组,作为 quick Google search reveals(例如,this one)。

解决方案4:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

最佳答案假定原始类型,但如果您想了解数组是否包含具有某些特征的 object,Array.prototype.some() 是一个优雅的解决方案:

const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]

items.some(item => item.a === '3')  // returns true
items.some(item => item.a === '4')  // returns false

它的好处是一旦找到元素就会中止迭代,这样就可以避免不必要的迭代周期。

此外,它非常适合 if 语句,因为它返回一个布尔值:

if (items.some(item => item.a === '3')) {
  // do something
}

正如 jamess 在评论中指出的那样,在 2018 年 9 月给出这个答案时,完全支持 Array.prototype.some():caniuse.com support table

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

我正在使用 Typescript,我的数组包含 Enum 类型的项目。 “包含”对我不起作用,这个解决方案有效。 Typescript 的任何其他解决方案将不胜感激。

解决方案5:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

ECMAScript 7 引入了 Array.prototype.includes。

它可以这样使用:

[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false

它还接受可选的第二个参数 fromIndex:

[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true

与使用 Strict Equality Comparison 的 indexOf 不同,includes 使用 SameValueZero 相等算法进行比较。这意味着您可以检测数组是否包含 NaN:

[1, 2, NaN].includes(NaN); // true

与 indexOf 不同的是,includes 不会跳过缺失的索引:

new Array(5).includes(undefined); // true

可以是 polyfilled 使其适用于所有浏览器。

解决方案6:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

假设您已经定义了一个这样的数组:

const array = [1, 2, 3, 4]

以下是检查其中是否存在 3 的三种方法。它们都返回 true 或 false。

Native Array 方法(自 ES2016 起)(兼容性表)

array.includes(3) // true

作为自定义 Array 方法(ES2016 之前)

// Prefixing the method with '_' to avoid name clashes
Object.defineProperty(Array.prototype, '_includes', { value: function (v) { return this.indexOf(v) !== -1 }})
array._includes(3) // true

简单的功能

const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

"~" 是一个对数字进行取整、取反和减 1 的运算符。 indexOf 如果失败则返回 -1,因此“~”将 -1 变为“0”。使用 ”!!”将数字转换为布尔值 (!!0===false)

解决方案7:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

这是 Array.indexOf 的 JavaScript 1.6 compatible 实现:

if (!Array.indexOf) {
    Array.indexOf = [].indexOf ?
        function(arr, obj, from) {
            return arr.indexOf(obj, from);
        } :
        function(arr, obj, from) { // (for IE6)
            var l = arr.length,
                i = from ? parseInt((1 * from) + (from < 0 ? l : 0), 10) : 0;
            i = i < 0 ? 0 : i;
            for (; i < l; i++) {
                if (i in arr && arr[i] === obj) {
                    return i;
                }
            }
            return -1;
        };
}

这看起来不错,但有点困惑: * 第 1 行和第 3 行的测试不是等效的吗? * 测试原型,如果有必要,将函数添加到 Array.prototype 中不是更好吗?

它们不是等价的。 [].indexOf 是 Array.prototype.indexOf 的简写。我们偏执的 Javascript 程序员不惜一切代价避免扩展原生原型。

[].indexOf 不是创建一个新数组然后访问 indexOf,而 Array.prototype.indexOf 只是直接访问原型吗?

@alex 是 [].indexOf === Array.prototype.indexOf(在 FireBug 中尝试),但反过来 [].indexOf !== Array.indexOf。

解决方案8:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

利用:

function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}

x ? true : false 通常是多余的。是这里。

@minitech 为什么说它是多余的?

array.indexOf(search) >= 0 已经是一个布尔值。只需 return array.indexOf(search) >= 0。

@minitech 很好,谢谢!其实我不知道这样的建筑可以退货。直到一些新的东西。

解决方案9:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

扩展 JavaScript Array 对象是一个非常糟糕的主意,因为您将新属性(您的自定义方法)引入到 for-in 循环中,这可能会破坏现有脚本。几年前,Prototype 库的作者不得不重新设计他们的库实现以删除这种东西。

如果您不需要担心与页面上运行的其他 JavaScript 的兼容性,那就去吧,否则,我会推荐更笨拙但更安全的独立函数解决方案。

我不同意。正是出于这个原因,for-in 循环不应该用于数组。使用流行的 js 库之一时,使用 for-in 循环会中断

解决方案10:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

表现

今天 2020.01.07 我在 Chrome v78.0.0、Safari v13.0.4 和 Firefox v71.0.0 上对 MacOs HighSierra 10.13.6 进行了 15 种选定解决方案的测试。结论

基于 JSON、Set 和意外发现 (K,N,O) 的解决方案在所有浏览器上最慢

es6 包含 (F) 仅在 chrome 上速度很快

基于 for (C,D) 和 indexOf (G,H) 的解决方案在大小数组上的所有浏览器上都非常快,因此它们可能是有效解决方案的最佳选择

循环期间索引减少的解决方案,(B)较慢可能是因为 CPU 缓存的方式起作用。

当搜索的元素位于数组长度的 66% 位置时,我还对大数组进行了测试,基于 for (C,D,E) 的解决方案给出了类似的结果(~630 ops/sec - 但 safari 和 firefox 上的 E 为 10 -20% 比 C 和 D 慢)

结果

https://i.stack.imgur.com/YPIG1.png

细节

我执行 2 个测试用例:对于具有 10 个元素的数组和具有 100 万个元素的数组。在这两种情况下,我们都将搜索到的元素放在数组中间。

让 log = (name,f) => console.log(${name}: 3-${f(arr,'s10')} 's7'-${f(arr,'s7')} 6- ${f(arr,6)} 's3'-${f(arr,'s3')}) 让 arr = [1,2,3,4,5,‘s6’,‘s7’,'s8 ',‘s9’,‘s10’]; //arr = new Array(1000000).fill(123); arr[500000]=7;函数 A(a, val) { var i = -1; var n = a.length; while (i++=0; } 函数 H(a,val) { return !!~a.indexOf(val); } 函数 I(a, val) { return a.findIndex(x=> xval)>=0; } 函数 J(a,val) { return a.some(x=> x=val); } 函数 K(a, val) { const s = JSON.stringify(val);返回 a.some(x => JSON.stringify(x) === s); } 函数 L(a,val) { return !a.every(x=> x!val); } 函数 M(a, val) { return !!a.find(x=> xval); } function N(a,val) { return a.filter(x=>x===val).length > 0; } 函数 O(a, val) { return new Set(a).has(val); } 日志(‘A’,A);日志(‘B’,B);日志(‘C’,C);日志(‘D’,D);日志(‘E’,E);日志(‘F’,F);日志(‘G’,G);日志(‘H’,H);日志(‘我’,我);日志(‘J’,J);日志(‘K’,K);日志(‘L’,L);日志(‘M’,M);日志(‘N’,N);日志(‘O’,O);此 Shippet 仅提供性能测试中使用的功能 - 它本身不执行测试!

小数组 - 10 个元素

您可以在您的机器上执行测试 HERE

https://i.stack.imgur.com/gDDCp.png

大数组 - 1.000.000 个元素

您可以在您的机器上执行测试 HERE

https://i.stack.imgur.com/cTL3s.png

解决方案11:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

单线:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}

array.filter(e=>e==x).length > 0 等价于 array.some(e=>e==x) 但 some 更有效

原文链接:https://www.huntsbot.com/qa/1jdO/how-do-i-check-if-an-array-includes-a-value-in-javascript?lang=zh_CN

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值